【问题标题】:Call order of constructors构造函数的调用顺序
【发布时间】:2014-01-28 19:23:37
【问题描述】:
#include <iostream>
using namespace std;    
struct A{
  A() {cout << "A" << endl;}
  A(int a) {cout << "A+" << endl;}
};

struct B : virtual A{
  B() : A(1) {cout << "B" << endl;}
};
struct C : virtual A{
  C() : A(1) {cout << "C" << endl;}
};
struct D : virtual A{
  D() : A() {cout << "D" << endl;}
};
struct E : B, virtual C, D{
  E(){cout << "E" << endl;}
};
struct F : D, virtual C{
  F(){cout << "F" << endl;}
};
struct G : E, F{
  G() {cout << "G" << endl;}
};

int main(){
  G g;
  return 0;
}

程序打印:

A
C
B
D
E
D
F
G

我想知道我应该使用什么规则来确定构造函数被调用的顺序。谢谢。

【问题讨论】:

  • 虚拟基由派生最多的类在任何其他基之前构造。
  • 要详细说明@KerrekSB 的评论以及A+ 未打印的事实,请注意将D 更改为调用A(1) 具有相同的行为,然后查看this one .现在三个都打电话给A(),但是G打电话给A(1)

标签: c++ inheritance constructor multiple-inheritance


【解决方案1】:

您应该遵循 C++ 标准中给出的规则:

[C++11: 12.6.2/10]: 在非委托构造函数中,初始化按以下顺序进行:

  • 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化类,其中“从左到右”是派生类中基类的出现顺序base-specifier-list
  • 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化(不管 mem-initializers 的顺序如何)。
  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem-initializers 的顺序无关)。
  • 最后,构造函数体的compound-statement被执行。

[ 注意: 声明顺序是为了确保基子对象和成员子对象以与初始化相反的顺序被销毁。 ——尾注]

【讨论】:

    【解决方案2】:

    虚拟基础子对象首先由派生最多的类构造,然后是任何其他基础。这是唯一有意义的方法,因为在运行时(因此是“虚拟的”)构建对象之前,虚拟基与最派生对象的关系是未知的。虚拟基的所有中间初始化器都被忽略。

    那么,您的虚拟基地是什么? G 派生自 EFE 虚拟派生自C,后者又虚拟派生自A,因此AC 是第一个。接下来,F 不会再添加任何虚拟碱基。接下来,E 有非虚基BD,按此顺序,接下来构造它们,然后E 完成。然后是F的非虚基DF就完成了。终于,G 完成了。

    总而言之,它是虚拟基础AC,然后是非虚拟基础BDEDF,然后是G 本身。

    【讨论】:

      【解决方案3】:

      您可以从 C++ 标准的引用中调查构造函数调用的顺序并尝试自己捕获它

      10 在非委托构造函数中,初始化在 下面的顺序:——首先,并且只针对最上面的构造函数 派生类(1.8),虚拟基类按顺序初始化 它们出现在定向的深度优先从左到右遍历 基类的无环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表。 — 然后,直接基类在 出现在基本说明符列表中的声明顺序 (不管 mem-initializers 的顺序如何)。 — 然后,非静态 数据成员按照它们在 类定义(同样不管 内存初始化器)。 — 最后,复合语句 构造函数体被执行。 [注:申报顺序为 强制确保基础和成员子对象在 初始化的相反顺序。 ——尾注]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-22
        • 2013-06-24
        • 1970-01-01
        • 2011-01-16
        • 2011-11-24
        • 2013-04-14
        相关资源
        最近更新 更多