您好, 如您所见,示例中的构造顺序为: - U1 U2 Y X V2 V1 V3 V4 B1 B2 D
我理解: U1 U2 YX 已初始化,因为 V2 是D的第一个直接虚拟继承,为了初始化它需要初始化这些首先 U1 U2 YX 。之后 V2 被初始化,但为什么 V1 在 V3 之前被初始化,尽管有 V3 的直接虚拟继承。
请忽略节点和箭头的编号,注意红色箭头是非虚拟继承,黑色箭头是虚拟的。
注意:可能会找到原始文档there。
答案 0 :(得分:3)
以下是我对该示例的理解。它符合施工顺序,所以我认为这是正确的。但是,我不确定。
首先,箭头的数量很重要,因为它们会告诉您基类定义的顺序。仅以D
为例,该类定义如下:
class D : virtual V2, B1, B2, virtual v3 {...}
鉴于此,我的下一步是遍历图形并将所有类放入深度优先顺序,无论它们是否为虚拟。大括号表示基类。括号表示已在我的班级列表中的虚拟基类:
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构建时调用的顺序相匹配。
答案 1 :(得分:0)
我只会解答有关V1和V3顺序的问题。
第一步是:
在深度优先,左右扫描中应用拓扑排序排名继承DAG,
- 虚拟和非虚拟继承一样。
根据这个规则,V1在V3之前出现:V1更深,而在V3的左边,无论继承类型如何。从左到右的顺序由从D到相关节点的连续祖先的直接继承等级定义。该等级由图的节点之间的边缘承载(因此不能被忽略):V3具有等级(3),而V2具有等级(1) - 并且还有(2,2)被较高的一个取消 - 并且V1具有等级(2,1)。因此,顺序是V2,然后是这三个节点之间的V1,然后是V3。
注意:为了清晰起见,图表没有以正确的左右顺序描述节点,假设V2和V3与其他节点保持关系的数量,而V1没有任何祖先。
第2步是:
构建所有虚拟基类(立即和非立即)
- 使用排名顺序。
- 不构造两次
[...]
V1和V3几乎都是继承的,V1代表B1,V3代表D,所以它们都是按照步骤1中建立的顺序在此步骤构建的。