c++ - 转换对基类的引用 : standard behaviour?

标签 c++ visual-c++ casting reference

我有如下情况:

class Getter
 {public: virtual void doSomething {std::cout<<"Nothing";};
  };
class Getter_A: public Getter
 {public: void doSomething {std::cout<<"A";};
  };
class Getter_B: public Getter
 {public: void doSomething {std::cout<<"B";};
  };

然后我有一段代码,我想在其中使用其中一个 Getter 东西。因此,用英语,我会这样:

{Getter & getter=wantA?Getter_A():Getter_B;
 getter.doSomething();
 };

当然,在 C++ 中这不太可行,因为三元运算符不够聪明,无法寻找公共(public)基类,所以我这样做:

{Getter & getter=wantA?(Getter &)Getter_A():(Getter &)Getter_B;
 getter.doSomething();
 };

这是优雅和可读的。问题是它是否适用于 C++。由于没有 C++ 编译器,而且我在引用书中找不到明确的答案,所以我在这里问。

共同点:我试过的“类似 C++ 的语言的编译器”执行以下操作:

  1. 创建一个 Getter_A 或一个 Getter_B 对象。
  2. 调用 doSomething
  3. 删除创建的对象。

悬而未决的问题是:要调用哪个 doSomething?

Mac 上的 Clang 调用 Getter_A::doSomething()Getter_B::doSomething()。因此,在幕后,Getter& 引用是对 Getter_A 对象或 Getter_B 对象的引用。

Visual C++ 6.0 调用 Getter::doSomething()。因此,在幕后,它从创建的对象中剥离了 Getter_Aness 并引用了一个裸露的 Getter 对象。如果 Getter::doSomething 是纯的而不是有一个主体,这将变得更加壮观。

现在,Visual C++ 6.0 以不是编译 C++ 而是完全不同的同名语言而闻名。然而,最好知道 C++ 本身(与这个或那个编译器编写者对 C++ 的看法相反)是否期望基类引用继续是对原始对象的引用它所有光彩夺目的虚拟性,或者在这种情况下,微软是否正确地在转换其引用时将对象剥离裸体。

我提出并测试的工作轮是:

{Getter_A a; Getter_B b;
 Getter &getter=*(wantA?(Getter *)&a:&b);
 getter.doSomething();
 }

因为编译器尊重指针的隐私,所以似乎到处都是安全的。但这是一种有点困惑的语言,最好知道真正的、符合标准的 C++ 编译器会如何处理对基类的引用转换。

最佳答案

我认为您的“优雅且可读”的方法有错字,而您打算阅读

{Getter & getter=wantA?(Getter &)Getter_A():(Getter &)Getter_B();
getter.doSomething();
};

(请注意 Getter_B 之后的 (),您的描述中缺少它)。

在任何情况下,这都会产生未定义的行为,因为所选对象在语句 getter.doSomething() 之前不再存在。因此,测试调用了哪个 doSomething() 是学术性的——即使两个编译器给出不同的结果,它们都是正确的。

您需要做的是确保您使用的对象在调用之前继续存在。

有多种方法,例如(本质上)您的“解决方法”。

 Getter_A a;
 Getter_B b;

 Getter &getter = wantA ? (Getter &) a : (Getter &) b;
 getter.doSomething();

或(更明确地)

 Getter_A a;
 Getter_B b

 Getter &ra(a), &rb(b);
 Getter &getter = wantA ? ra : rb;
 getter.doSomething();

关于c++ - 转换对基类的引用 : standard behaviour?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56077473/

相关文章:

visual-studio-2008 - Microsoft 增量链接器已停止工作

c++ - 在 MSVC 的 Debug模式下分配给 std::future 时崩溃

Java 引用未初始化的类

c# - 在 C# 中实现 "foos"的集合,它具有 "bars"的子集

java - 将 bigint 转换为 long

c++ - Linux 堆栈跟踪转储

c++ - 预处理器指令 "Using"

html - 如何使用 libMongoose/Embedded Mongoose 发送 HTML 和图像?

c++ - 从控制台读取 : operator>> for enum inside template class

c++ - 我对 vtable 内容的困惑