#include <iostream>
#include <string>
using namespace std;
class A
{
private:
int ai;
string as;
};
class B : public A
{
private:
int bi;
string bs;
};
int main()
{
B bob;
return 0;
}
A类和B类具有默认构造函数。我知道将首先调用类A默认构造函数,然后调用B默认构造函数。但问题是内部是如何发生的?数据成员是否以继承顺序构建?编译器如何/在何处从dervied ctor调用base ctor?
答案 0 :(得分:2)
基本上首先初始化基类,然后按声明顺序初始化数据成员。虚拟基类是一个例外,它首先被初始化,而且来自最派生的类。另一个例外是委托构造函数。
Standardeese:在C ++ 11中,这由§12.6.2/ 10指定:
“在非委派构造函数中,初始化按以下顺序进行:
- 首先,仅针对派生程度最高的类(1.8)的构造函数,初始化虚拟基类 它们出现在基类的有向无环图的深度优先从左到右遍历中的顺序, 其中“从左到右”是派生类 base-specifier-list 中基类出现的顺序。
- 然后,直接基类按声明顺序初始化,因为它们出现在 base-specifier-list 中 (无论 mem-initializers 的顺序如何。)
- 然后,按照在类定义中声明的顺序初始化非静态数据成员 (再次无论 mem-initializers 的顺序如何)。
- 最后,执行构造函数体的复合语句。
[注意:声明命令的目的是确保基础和成员子对象在 初始化的逆序。 -end note ]
关于它如何在内部工作,一种常见的技术是构造函数调用其关联的基础和普通成员构造函数。如果忽略虚拟基础和构造函数委托,并考虑实例化类T,那么当您实例化T时,首先发生的是调用T构造函数。但这还不是T实例本身的初始化。执行仍在该构造函数的内存初始化列表中。在这里,它调用各种基本和非基本成员构造函数(递归地发生相同的情况)。最后执行构造函数体。