一、类对象成员的构造
先构造成员
再构造自身(调用构造函数)
二、派生类构造函数
派生类可能有多个基类,也可能包括多个成员对象,在创建派生类对象时,派生类的构造函数除了要负责本类成员的初始化外,还要调用基类和成员对象的构造函数,并向它们传递参数,以完成基类子对象和成员对象的建立和初始化。
派生类只能采用构造函数初始化列表的方式向基类或成员对象的构造函数传递参数,形式如下:
派生类构造函数名(参数表): 基类构造函数名(参数表), 成员对象名1(参数表) {}
三、构造函数和析构函数调用次序
派生类对象的构造
- 先构造基类
- 再构造成员
- 最后构造自身(调用构造函数)
基类构造顺序由派生层次决定:最远的基类最先构造
- 成员构造顺序和定义顺序相同,与初始化列表的顺序无关
- 析构函数的析构顺序与构造相反
代码示例
#include <iostream>
using namespace std;
class A {
int x;
public:
A(int i = 0) {
x = i;
cout << "A constructor: " << x << endl;
}
};
class B {
int y;
public:
B(int i) {
y = i;
cout << "B constructor: " << y << endl;
}
};
class C {
int z;
public:
C(int i) {
z = i;
cout << "C constructor: " << z << endl;
}
};
class D: public B {
public:
C c1;
A* a1 = new A(10);
A a0, a4;
D(): a4(4), c1(1), B(1) {
cout << "D constructor" << endl;
}
};
int main(int argc, char const *argv[]) {
D d;
return 0;
}
B constructor: 1 // 先调用基类构造函数
C constructor: 1 // 按照声明的顺序调用成员对象的构造函数,c1
A constructor: 10 // a1
A constructor: 0 // a0
A constructor: 4 // a4
D constructor // 最后才是自身
explicit关键字
class A {
public:
int x;
A(int x) {this->x = x;} // 重载构造函数
A(const A &a) {this->x = a.x;} // 拷贝构造函数
};
int main() {
A a1(5); // 显示调用初始化函数
A a2 = 9; // 隐式调用初始化函数
A a3(a1); // 显示调用拷贝构造函数
A a4 = a1 // 隐式调用拷贝构造函数
return 0;
}
没加explicit
时显示调用和隐式调用都可以
加了explicit
就相当于禁用隐式调用
class A {
public:
int x;
explicit A(int x) {this->x = x;}
explicit A(const A &a) {this->x = a.x;}
};
int main() {
A a1(5); // 显示调用初始化函数
// A a2 = 9; // error
A a3(a1); // 显示调用拷贝构造函数
// A a4 = a1 // error
return 0;
}