【发布时间】:2015-07-20 16:34:45
【问题描述】:
手头的问题很难描述,因此代码放在前面以便更清楚。
struct Base
{
int b;
virtual void foo(){cout << b << endl;}
Base(int x) : b(x){}
};
struct Derived1 : Base //not virtual
{
virtual void foo(){/*Derived2's code*/}
Derived1() : Base(1){}
};
struct Derived2 : Base //not virtual
{
virtual void foo(){/*Derived2's code*/}
Derived2() : Base(2){}
};
struct MultiInheritance : Derived1, Derived2
{
void bar1()
{
//needs to access Derived1's Base foo()
}
void bar2()
{
//needs to access Derived2's Base foo()
}
};
假设在一些奇怪的奇怪场景中,我想要一个基类MultiInheritance,它有两个基类Derived1 和Derived2,它们有一个共同的非虚拟基类@987654325 @。
MultiInheritance 中有两个Base,如何指定我希望在MultiInheritance 中访问哪个Base 类?
上面的代码通过多次转换似乎可以正常工作,但我不确定这是否是已定义的行为。如果是,编译器如何实现它来满足多态性的需求?一方面,virtual 调用应该都产生相同的virtual 函数表,但另一方面,如果它这样做,它不会输出不同的答案。
编辑
我想强调Base 类必须是非虚拟的
EDIT2
深表歉意,我严重歪曲了自己。上面的代码更新后更好地反映了我原来的问题。
【问题讨论】:
-
你认为哪个正确
Base?或者你的问题是如何做到只有一个Base? -
您的分析是正确的,编译器将构建一个正确的 vtable,反映两个基类的存在。为避免这种情况,您需要虚拟继承,并且 vtable 结构将变得更加复杂。
-
您的示例中没有歧义,它的行为与书中应有的完全一样。 “虚拟表”是一个实现细节。没有人说每个实现每个类必须有一个 vtbl,或者每个 vtable 中的每个函数签名必须有一个条目。事实上,对于任何使用 vtables 的实现来说,上述至少一项很可能是不正确的。
-
这被称为“可怕的死亡钻石”并非空穴来风。只是不要这样做。如果出于某种奇怪的原因,你觉得不得不在任何地方开枪,就说
static_cast<Derived1*>(this)。 -
@EduardoLeón“语义不明,有很多特殊情况”如果这不是“本质上不好”,那么我不知道是什么。 “在 OCaml 中” OCaml 中的菱形(和多重)继承与 C++ 完全不同。从字面上看,没有共同点。
标签: c++ polymorphism multiple-inheritance