我遇到了这个令我困惑的问题。
这个代码是:
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的构造顺序是什么?
这是我为了简化而构建的图表
首先,我想考虑到没有虚拟继承的事实来回答这个问题。关键字virtual
已被public
替换为
B1,V1,D1, [B3,B1,B2,V2,D2] , X
但是,我不确定当虚拟继承出现时我将如何处理这个问题。提到的代码。我读到除了virtual bases被赋予优先权之外它完全相同。这里有哪些虚拟基地?关于如何解决这个问题的任何建议?
答案 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