你好
如您所见,示例中的构造顺序为:– U1 U2 Y X V2 V1 V3 V4 B1 B2 D
我知道: U1 U2 Y X 已初始化,因为 V2 是D的第一个直接虚拟继承,并且要对其进行初始化,需要初始化这些第一个 U1 U2 Y X 。在初始化了 V2 之后,但是为什么 V1 在 V3 之前被初始化,尽管从 V3 直接获得了虚拟继承。
请忽略节点和箭头的编号,请注意红色箭头是非虚拟继承,黑色箭头是虚拟。
注意:原始文档可以在there中找到。
最佳答案
这是我对示例的理解。它符合施工顺序,因此我认为它是正确的。但是,我不确定。
首先,箭头的数字很重要,因为它们告诉您定义基类的顺序。仅以D
为例,该类的定义如下:
class D : virtual V2, B1, B2, virtual v3 {...}
鉴于此,我的下一步是遍历图并将所有类置于深度优先顺序,而不管它们是否是虚拟的。大括号表示基类。括号表示我的类(class)列表中已有一个虚拟基类:
D {V2 {X {U1, U2}, Y {(U2), (U1)}}, B1 {V1, (V2), V3 {(Y), (U2)}, V4}, B2 {(V4-V1)}, (V3)
对我来说,这说
鉴于此,我现在将删除冗余基类,保留以下内容:
D {V2 {X {U1, U2}, Y}, B1 {V1, V3, V4}, B2}
下一部分是找到非虚拟基类,并对我的列表进行调整。
关于这一点的一个额外要点:考虑到您的问题,我希望您也认为U2应该在U1之前,因为Y是在X之前构造的,而在Y中,U2首先是派生的。但是,这不会发生。相反,X的虚拟基类是按顺序完成的,然后是Y,最后是X。
这会将我的列表调整为以下内容:
D {V2 { {U1, U2}, Y, X}, B1 {V1, V3, V4}, B2}
最后,B1是非虚拟的,因此它必须位于V1,V3和V4之后。这留下:
D {V2 { {U1, U2}, Y, X}, {V1, V3, V4}, B1, B2}
请注意,B2也是非虚拟的,如果它不是我列表中的最后一个,则需要考虑。
这给了我令我满意的命令。唯一的问题是,我在基类之前列出了派生类,并且我们知道基类是首先构造的。剩下的唯一两个问题是
因此,我将调整列表以将这两个项目移动到X后面的V2和B2之后的D。
{ { {U1, U2}, Y, X} V2, {V1, V3, V4}, B1, B2} D
现在,我将删除括号和:
U1, U2, Y, X, V2, V1, V3, V4, B1, B2, D
您可以看到它与图中的构造函数顺序匹配,并且确实与我使用Visual Studio 2012构建时调用的顺序匹配。
关于c++ - C++虚拟继承初始化顺序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15885601/