在初始化变量之前调用父类构造函数,还是编译器首先初始化类的变量?
例如:
class parent {
int a;
public:
parent() : a(123) {};
};
class child : public parent {
int b;
public:
// question: is parent constructor done before init b?
child() : b(456), parent() {};
}
答案 0 :(得分:16)
是的,基类在派生类的成员之前和构造函数体执行之前初始化。
在非委托构造函数中,初始化继续进行 以下顺序:
- 首先,仅适用于最多的构造函数 派生类(1.8),虚拟基类按顺序初始化 它们出现在深度优先的从左到右的遍历中 基类的非循环图,其中“从左到右”是基数的顺序 派生类中基类的外观 基本符列表。
- 然后,在中初始化直接基类 声明顺序,因为它们出现在base-specifier-list中 (不管mem-initializers的顺序如何)。
- 然后,非静态 数据成员按照在其中声明的顺序进行初始化 类定义(再次无论顺序如何 MEM-初始化)。
- 最后,复合声明了 构造函数体被执行。
答案 1 :(得分:3)
是的,始终在派生类之前调用父构造函数。否则,派生类不能“改变”父类设置的内容。
答案 2 :(得分:2)
正如一些建议一样,如果您不确定,通常可以自己测试这样的事情:
#include <iostream>
using namespace std;
class parent {
protected:
int a;
public:
parent() : a(123) { cout << "in parent(): a == " << a << endl; };
};
class child : public parent {
int b;
public:
// question: is parent constructor done before init b?
child() : b(456), parent() { cout << "in child(): a == " << a << ", b == " << b << endl; };
};
int main() {
child c;
return 0;
}
打印
in parent(): a == 123
in child(): a == 123, b == 456
答案 3 :(得分:0)
是的,对象的构造从父类开始并到达子类,因此构造函数调用按此顺序进行。在破坏的情况下,这恰恰相反。
答案 4 :(得分:0)
将派生类视为其基类的额外添加或扩展,添加因此它添加到某些东西(这个东西必须已经存在)。 那么,另一个问题是成员的初始化。在这里,您提供了默认构造函数
public:
parent() : a(123) {};
因此,即使您以这种方式创建父级,该成员也将使用123进行默认初始化:
parent p;
如果没有默认构造函数初始化具有值
的对象class parent {
public:
int a;
};
比成员默认的那样,如果类是P.O.D那么int将默认初始化为0,但如果不是,即你提供更多成员,如字符串或向量
class parent {
public:
int a;
std::string s;
std::vector<int> v;
};
如果没有初始化它的默认构造函数,int将具有随机值。