3

嗨,正如您在示例中看到的构造顺序是: – U1 U2 YX V2 V1 V3 V4 B1 B2 D

我的理解是:U1 U2 YX被初始化是因为V2是第一个直接虚拟继承到 D 的,为了初始化它需要初始化这些U1 U2 YX。在那之后V2被初始化,但是为什么V1在V3之前被初始化,虽然从V3有直接的虚拟继承。

请忽略节点和箭头的数量,注意红色箭头是非虚拟继承,黑色箭头是虚拟的。

注意:原始文件可以在那里找到。

4

2 回答 2

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。
  • V2 需要 X,X 需要 U1 和 U2。
  • Next 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,它需要在它的孩子之后。

所以我将调整我的列表以移动这两个项目,V2 在 X 之后,D 在 B2 之后。

{ { {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 构建时调用的顺序相匹配。

于 2013-04-08T19:18:31.993 回答
0

我只会解决您关于 V1 和 V3 顺序的问题。

第一步是:

在深度优先左右扫描中应用拓扑排序排序继承 DAG ,

  • 虚拟和非虚拟继承被同等对待

根据这条规则,V1 在 V3 之前:V1 更深,在 V3 的左侧,无论继承类型如何。从左到右的顺序由从 D 到相关节点的连续祖先的直接继承等级定义。该等级由图节点之间的边承载(因此不能忽略):V3 具有等级 (3),而 V2 具有等级 (1) - 并且 (2,2) 被较高的取消 - V1 的秩为 (2, 1)。因此,这 3 个节点之间的顺序是 V2,然后是 V1,然后是 V3。

注意:考虑到 V2 和 V3 与其他节点保持的关系数量,该图没有以正确的左右顺序描述节点,而 V1 没有任何祖先。

第2步是:

构造所有虚拟基类(立即和非立即)

  • 使用排名顺序
  • 不要构造两次

[...]

V1 和 V3 都是虚拟继承的,V1 用于 B1,V3 用于 D,因此它们都在此步骤中按照步骤 1 中确定的顺序构建。

于 2013-04-08T18:57:27.610 回答