2013-04-08 125 views
3

C++虚拟继承初始化顺序

您好, 正如你可以看到在例子中的施工顺序是: - U1 U2 YX V2 V1 V3 V4 B1 B2 d

我明白:U1 U2 YX已初始化,因为V2是对D的第一个直接虚拟继承,并且为了初始化它,需要初始化这些第一个对象。之后V2被初始化,但为什么V1之前V3初始化虽然离V3直接虚拟继承。

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

注意:原始文档可能会被发现there

+1

@Basile不,为什么?这是无稽之谈,这个问题完全是关于话题的。 – 2013-04-08 17:53:33

+0

@Basile,它不是脱离主题的问题,它不需要代码来理解问题或在stackoverflow中发布,这是C++虚拟继承的理解问题,图是理解概念的最简单方法,请忽略问题是否你不知道答案。 – nabil 2013-04-08 17:54:46

+4

我想downvote该图的创建者,但不是OP。 – dyp 2013-04-08 17:57:17

回答

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,它需要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是虚拟的,桑尼将不得不X.前

加分一下:鉴于你的问题,我希望你也觉得U2应该在U1之前,因为Y是在X之前和Y之前构造的,U2是先得出的。但是,这并没有发生。相反,X的虚基类,以便完成,则Y,最后十

这个调整我的名单如下:

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,和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.

+0

谢谢你的详细答案,我明白了一切,直到我得到了“额外的点”,当前是Y,为什么我们必须通过X中的继承顺序初始化,如果我们不在X中!!?是因为你通过X而不是Y探索了U1和U2? – nabil 2013-04-08 19:56:09

+1

@nabil,是的。那是对的。因为V2本质上被声明为'class V2:X,virtual Y',所以需要为X创建X的虚拟基类。然后,在构造X之前,需要构造Y,因为Y是一个虚拟的V2和X的基类不是。如果Y也有一个不是X的基类的虚拟基类,那么在X之前也需要这个类。 – 2013-04-08 20:36:56

+0

现在我的问题就是这样,当你上面说过“V2需要X和Y,其中Y是虚拟的,所以Y必须在X之前。“为什么我们也没有将这个顺序应用于:D当它需要B1和V3,V3是虚拟的,那么V3会先到? – nabil 2013-04-08 21:38:57

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

+0

谢谢,但是如果我应用上面提到的规则,为什么V2在V1之前初始化,它的深度相同,V1在V3的左侧。 – nabil 2013-04-08 19:45:09

+0

请参阅我的更新,阐明左右顺序的概念。 – didierc 2013-04-08 20:41:03

+0

图形视觉表示可能是那里的误导,因为正如我所说的,V1实际上是V2和V3之间的左边顺序。也就是说,我并没有完全解释整个算法的执行过程。另一个答案在这方面显然更胜一筹。 – didierc 2013-04-08 20:59:34