【问题标题】:ladder-like C++ virtual inheritance阶梯式 C++ 虚拟继承
【发布时间】:2018-09-05 08:33:39
【问题描述】:

如果我有如下的类继承关系

               a
              /  \
             b    c
              \   |
               |  d
                \/ \
                e   f
                 \ /
                  g

以下定义是否正确?

    class A {};
    class B: public virtual A {};
    class C: public virtual A {};
    class D: public C {};
    class E: public B, public virtual D  {};
    class F: public virtual D {};
    class G: public E, public F {};

我让 A 和 D 都虚拟继承,因为我假设每个联合类都需要是虚拟的。

我也不确定 C++ 如何定义上述情况的构造函数顺序。链接 https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order

最先被执行的构造函数是虚基 层次结构中的任何位置的类。它们按照它们的顺序执行 出现在基图的深度优先从左到右遍历中 类,其中从左到右是指基的出现顺序 类名。

在所有虚拟基类构造函数完成后, 构造顺序一般是从基类到派生类。这 如果你想象第一个细节是最容易理解的 编译器在派生类的 ctor 中所做的事情是创建一个 对其非虚拟基类的 ctor 的隐藏调用(提示:那是 许多编译器实际上这样做的方式)。所以如果类 D 继承 从 B1 和 B2 相乘,首先执行 B1 的构造函数,然后 B2 的构造函数,然后是 D 的构造函数。这条规则是 递归应用;例如,如果 B1 继承自 B1a 和 B1b,并且 B2继承自B2a和B2b,那么最终的顺序是B1a,B1b,B1, B2a、B2b、B2、D。

请注意,顺序 B1 然后 B2(或 B1a 然后 B1b)由下式确定 基类出现在声明中的顺序 类,而不是初始化器出现在派生中的顺序 类的初始化列表。

如果是,顺序是这样的吗?

  A, D, B, C, D, F, G

我不希望在 C 之前构造 D。正确的构造顺序是什么?

【问题讨论】:

    标签: c++ multiple-inheritance virtual-inheritance


    【解决方案1】:

    在构造G 类的对象时,首先初始化虚拟基类。这导致AD 的构造函数被调用。 D 的构造函数将构造它的基础 C 对象。然后将调用G 的非基类的构造函数,即EFE 的构造函数将调用 B 的构造函数。这给出了最终的顺序:

    A C D B E F G
    

    【讨论】:

      【解决方案2】:

      我添加了调用printf 的构造函数来观察会发生什么(代码在Godbolt 上提供给好奇者)。使用 clang(6.0.0 版)和 gcc(6.4.0 和 7.3.0 版)我得到的顺序是:

      A
      C
      D
      B
      E
      F
      G
      

      这符合我的预期。 AD 必须首先构造,但你不能在没有 C 的情况下构造 D(想象一个更复杂的示例,其中 D 的构造函数调用到 C。一旦所有 virtual继承已经满足,构造函数按照我们期望的顺序被调用。

      【讨论】:

        猜你喜欢
        • 2016-03-26
        • 2011-01-08
        • 1970-01-01
        • 2017-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多