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

时间:2014-09-24 03:06:47

标签: 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 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 { };

问题:X的构造顺序是什么?

这是我为了简化而构建的图表

enter image description here

首先,我想考虑到没有虚拟继承的事实来回答这个问题。关键字virtual已被public替换为

B1,V1,D1, [B3,B1,B2,V2,D2] , X

但是,我不确定当虚拟继承出现时我将如何处理这个问题。提到的代码。我读到除了virtual bases被赋予优先权之外它完全相同。这里有哪些虚拟基地?关于如何解决这个问题的任何建议?

1 个答案:

答案 0 :(得分:2)

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

  

在非委托构造函数中,初始化继续进行   以下顺序:

     
      
  • 首先,仅对于派生程度最高的类(1.8)的构造函数,虚拟基类按照它们出现的顺序进行初始化   深度优先从左到右遍历有向无环图   基类,其中“从左到右”是出现的顺序   派生类 base-specifier-list
  • 中的基类   
  • 然后,直接基类按声明顺序初始化,因为它们出现在 base-specifier-list 中(无论顺序如何)    MEM-初始化)。
  •   
  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样无论顺序如何    MEM-初始化)。
  •   
  • 最后,执行构造函数体的复合语句
  •   

因此,如果V1和V2是虚拟基础,则构造变为V1 - > V2 - &gt; D1 - &gt; D2 - &gt; X的复合陈述。 V1的构造函数将首先构造一个B1,然后执行它的主体。 V2的构造函数将构造一个B1和一个B2,然后执行它的主体。 D2的构造函数将在执行其主体之前构造一个B3。 (因为D1和D2都不是最派生的类,它们的构造函数不构造虚拟基础V1或V2。)因此整个打印输出顺序是B1 - > V1 - &gt; B1 - &gt; B2 - &gt; V2 - &gt; D1 - &gt; B3 - &gt; D2 - &gt; X

如果V1和V2不是虚拟基础,那么X的结构就是D1 - &gt; D2 - &gt; X.D1具有单个直接基础V1,V1具有单个直接基础B1,因此您获得B1 - > V1 - &gt; D1为第一部分。类似地,您构建B3 - &gt; B1 - &gt; B2 - &gt; V2 - &gt; D2为第二部分,因此整体顺序为B1 - > V1 - &gt; D1 - &gt; B3 - &gt; B1 - &gt; B2 - &gt; V2 - &gt; D2 - &gt; X