你好
如您所见,示例中的构造顺序为:– 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。
  • V2需要X,这需要U1和U2。
  • 下一个V2需要Y,它需要U2和U1,但是两者都已在我的列表中。
  • 下一个D需要B1。
  • B1需要V1,V2,V3和V4,而V2已经在我的列表中。
  • V3需要Y和U2,但两者都已在我的列表中。
  • 下一个D需要B2,它需要V4到V1,这些都已经在我的列表中了。
  • 最后,D需要V3,但同样,它已经在我的列表中。

  • 鉴于此,我现在将删除冗余基类,保留以下内容:
    D {V2 {X {U1, U2}, Y}, B1 {V1, V3, V4}, B2}
    

    下一部分是找到非虚拟基类,并对我的列表进行调整。
  • V2需要X和Y,其中Y是虚拟的,因此Y必须在X之前。

    关于这一点的一个额外要点:考虑到您的问题,我希望您也认为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也是非虚拟的,如果它不是我列表中的最后一个,则需要考虑。

    这给了我令我满意的命令。唯一的问题是,我在基类之前列出了派生类,并且我们知道基类是首先构造的。剩下的唯一两个问题是
  • D,它必须是最后一个。
  • V2,必须在其子项之后。

  • 因此,我将调整列表以将这两个项目移动到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/

    10-11 22:42
    查看更多