C++ 复杂的构造顺序-涉及虚拟继承

C++ 复杂的构造顺序-涉及虚拟继承,c++,virtual-inheritance,C++,Virtual Inheritance,我遇到了这个问题,把我弄糊涂了 这方面的代码是: struct B1 { B1(){std::cout << "B1\n";} }; struct V1 : public B1 { V1(){std::cout << "V1\n";} }; struct D1 : virtual public V1 {D1(){std::cout << "D1\n";} }; struct B2 {B2(){std::cout << "B2\n

我遇到了这个问题,把我弄糊涂了

这方面的代码是:

  struct B1 { B1(){std::cout << "B1\n";} };
  struct V1 : public B1 {  V1(){std::cout << "V1\n";} };
  struct D1 : virtual public V1 {D1(){std::cout << "D1\n";} };

  struct B2 {B2(){std::cout << "B2\n";} };
  struct B3 {B3(){std::cout << "B3\n";} };
  struct V2 : public B1, public B2 {V2(){std::cout << "V2\n";} };
  struct D2 : public B3, virtual public V2 {D2(){std::cout << "D2\n";} };
  struct X : public D1, public D2 { };
然而,当虚拟继承出现时,我不确定如何处理这个问题。前面提到的代码。我读到,它的解决方法完全相同,只是有优先权。这里的虚拟基地是什么?关于如何解决这样的问题有什么建议吗?

以下是规则(§12.6.2[class.base.init]/p11):

在非委托构造函数中,初始化在 顺序如下:

  • 首先,并且仅对于派生最多的类(1.8)的构造函数,虚拟基类按照它们在 有向无环图的深度优先左向右遍历 基类,其中“从左到右”是 派生类基类说明符列表中的基类
  • 然后,直接基类按照它们在基说明符列表中出现的声明顺序进行初始化(不管 mem初始值设定项)
  • 然后,非静态数据成员将按照它们在类定义中声明的顺序进行初始化(同样,与 mem初始值设定项)
  • 最后,执行构造函数主体的复合语句
因此,如果V1和V2是虚拟基,那么构造将是V1->V2->D1->D2->X的复合语句。V1的构造函数将首先构造B1,然后执行其主体。V2的构造函数将构造B1和B2,然后执行其主体。D2的构造函数将在执行其主体之前构造B3。(因为D1和D2都不是最派生的类,它们的构造函数不构造虚拟基V1或V2。)因此,整体打印输出顺序是B1->V1->B1->B2->V2->D1->B3->D2->X


如果V1和V2不是虚基,那么X的构造就是D1->D2->X。D1有一个直接基V1,V1有一个直接基B1,所以第一部分是B1->V1->D1。类似地,您为第二部分构造了B3->B1->B2->V2->D2,因此总体顺序是B1->V1->D1->B3->B1->B2->V2->D2->X。

D2不调用
V2
的构造函数,因为它不是最派生的类?@0x499602D2在虚拟基类中?是的。第一个要点不清楚,它是否说所有出现在图中的虚拟基类都是先初始化的;或者仅仅是那些直接从?@MattMcNabb继承的X,这是DAG的深度优先遍历-它必须是所有虚拟基。如果它只是直接的虚拟基地,那么遍历整个DAG是没有意义的。图表不正确,两个
B1
实例是分开的。我不确定如果
V1
virtualpublic B1
但是
V2
是(非虚拟的)
public B1
会发生什么@Mattmcnab虚拟的由
X
的构造函数虚拟构造,非虚拟的由V2的构造函数非虚拟构造;最终将得到两个
B1
子对象。
B1,V1,D1, [B3,B1,B2,V2,D2] , X