构造函数的调用顺序
Call order of constructors
#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
我想知道应该使用什么规则来确定调用构造函数的顺序。谢谢
您应该遵循C++标准中给出的规则:
[C++11: 12.6.2/10]:
在非委托构造函数中,初始化按以下顺序进行:
- 首先,仅对于最派生类(1.8)的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先左到右遍历中出现的顺序进行初始化,其中"从左到右"是派生类基说明符列表中基类的出现顺序
- 然后,直接基类按照它们在基说明符列表中出现的声明顺序进行初始化(无论mem初始化器的顺序如何)
- 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,与mem初始化器的顺序无关)
- 最后,执行构造函数主体的复合语句
[注意:声明顺序是为了确保基本子对象和成员子对象以与初始化相反的顺序销毁。--结束注释]
虚拟基子对象首先由最派生的类构造,然后再构造任何其他基。这是唯一有意义的方法,因为在运行时构建对象之前,虚拟基与大多数派生对象的关系是未知的(因此是"虚拟的")。忽略虚拟基的所有中间初始值设定项。
那么,你的虚拟基地是什么?CCD_ 2由CCD_ 3和CCD_。E
实际上是从C
派生而来的,而CCD_6又实际上是从CCD 7派生而来,因此A
、C
是第一位的。接下来,F
不添加任何进一步的虚拟基地。接下来,E
具有非虚拟碱基B
和D
,按顺序,它们被构造成下一个,然后E
是完整的。然后是F
的非虚拟基D
,并且F
是完整的。最后,G
是完整的。
总之,它是虚拟碱基A
、G
0,然后是非虚拟碱基B
、D
、E
和D
、F
,然后是G
本身。
您可以从C++标准的这句话中调查构造函数调用的顺序,并尝试自己捕获
10在非委托构造函数中,初始化在以下顺序:--首先,并且仅适用于构造函数的派生类(1.8),虚拟基类按以下顺序初始化它们出现在有向的从左到右的深度优先遍历中基类的非循环图,其中"从左到右"是基类在派生类中的外观基说明符列表。--然后,直接基类在中初始化在基说明符列表中出现的声明顺序(不管mem初始化程序的顺序如何)。--然后,非静态数据成员按照在中声明的顺序进行初始化类定义(同样与mem初始化程序)。--最后构造函数主体被执行。【注:申报顺序为被授权确保基本子对象和成员子对象在初始化的相反顺序--尾注]
- 函数调用中参数的顺序重要吗
- C++:使用方法调用析构函数的顺序是什么?
- 犰狳的 print() 方法和 cout 在从 Rcpp 调用时顺序不一致
- 以 f() + g() 调用顺序的 C++ 函数
- QNetworkReply::done() 信号是按顺序调用还是同时调用?
- 函数中调用的构造函数的顺序
- x64 函数调用参数推送/移动顺序 (MSVC)
- C++销毁顺序:在类析构函数之前调用字段析构函数
- COUT 内部函数调用的顺序
- 如何创建跟踪以显示存在递归的调用顺序
- 以特定顺序调用功能
- variadic模板函数会以相反的顺序调用lambda参数
- 具有类层次结构时按什么顺序调用方法
- 执行 Qt::QueuedConnection 信号始终按顺序调用
- Qt - 解决一个插槽上的两个顺序调用,并且仅执行一次操作
- 我的C++DLL返回两个顺序调用混合的数据
- 如何强制按顺序调用几个函数
- 对 R 的子顺序 C 调用不起作用
- std::remove_if是否保证按顺序调用predicate ?
- C++ 使用 sqlite:"库例程不按顺序调用