c++ - 复杂菱形问题:C++ 虚拟继承

  显示原文与译文双语对照的内容

我有一个钻石问题,看起来像这样:


 __ A


/|


 | B | 


v|/v v|v v


 B2 B3 C


 v/v/


 B4/


 /


 D



为了获得最好的虚拟继承,我尝试了很多方法,但是我找不到任何解决方案。 类A 包含一个位置。 下面是一个示例输出:


Call: A() position pointer is: 0x2203be8


Call: B()


Call: B2() position pointer is: 0x2203be8


Call: B3() position pointer is: 0x2203be8


Call: C() position pointer is: 0x2203a28


Call: B4() position pointer is: 0x2203be8


Call: D() position pointer is: 0x2203a28



为什么D 和C 没有相同的位置指针? 为什么这里 A::position 没有构造函数? 我应该用什么虚拟继承来解决这个问题? 谢谢。

编辑:

下面是一个代码示例:


class A;


class B;


class B2 : public virtual B, public virtual A;


class B3 : public virtual B, public virtual A;


class C : public virtual A;


class B4 : public virtual B2, public virtual B3;


class D : public B4, public C;



编辑 2: 要生成输出,我将这里代码放在每个构造函数中:


A::A()


{


 std::cerr <<"Call: A() position pointer is:" <<&_position <<std::endl;


}



时间: 原作者:

由于你说下面的代码对我已经有的实现有效,然后显然代码不是问题。 问题在于你的设置中的其他内容;可能是编译器 Bug 。 应该缩小问题的原因;因为代码本身被排除作为问题,可以能最好的下一步是更新编译器。

在任何情况下,这个问题都是针对你的设置。 如果你找到一个可能适用于别人的解决方案,那么你应该回来并发布它。 在那之前我决定关闭这个问题。

我在尝试重现你的问题。 下面是我使用的代码:


#include <iostream>



struct A { int a; };


struct B { int b; };


struct B2 : virtual B, virtual A {};


struct B3 : virtual B, virtual A {};


struct B4 : virtual B2, virtual B3 {};//these virtuals are unnecessary in this case...


struct C : virtual A {};


struct D : B4, C {};



int main() {


 D d;


 std::cout <<&((B4*)&d)->a <<'n';


 std::cout <<&((B3*)(B4*)&d)->a <<'n';


 std::cout <<&((B2*)(B4*)&d)->a <<'n';


 std::cout <<&((A*)(B2*)(B4*)&d)->a <<'n';


 std::cout <<&((A*)(B3*)(B4*)&d)->a <<'n';


 std::cout <<&((C*)&d)->a <<'n';


 std::cout <<&((A*)(C*)&d)->a <<'n';


}



但是我得到的结果是预期的,其中 a 成员对每个对象都是相同的。 如果用户也在构造函数中输出地址,则会得到相同的结果: http://ideone.com/8FdQ1O

如果我稍微更改并从c的定义中删除 virtual 关键字,请执行以下操作:


...


struct C : A {};


...



( 版本使用构造函数 )

然后我看到了你描述的问题,它的中C 有一个与,所使用的,对象不同的,对象。

你确定在所有需要的地方都使用 virtual 关键字? 你所展示的结果表明你在某个地方丢失了。 我还注意到,所显示的输出与你所显示的代码 Fragments 顺序不一样;输出显示 A(),但是代码表明首先执行 B() 。

虚拟继承的方式是,对于继承树的任何地方实际上继承的每个类型,最派生的类型都包含一个虚拟子对象。 此外,大多数派生类型将包含针对非虚拟继承的每个实例的子对象:


struct A {};


struct B : virtual A {};


struct C : A, B {};


struct D : virtual A, C {};


struct E : A, D {};


struct F : virtual A, E {};


struct G : A, F {};



G g;



g 总共包含四个 a 子对象,每次 a 都不是继承的( 在 CEg 中),一次 a 实际上是继承的( 在 BDF 中) 。

原作者:
...