当一个对象拥有过多的子对象时,有必要搞明白构造和析构的顺序。
首先初始化基类,然后是自己的成员变量
//: C14:Order.cpp
// Constructor/destructor order
#include <fstream>
using namespace std;
ofstream out("order.out");
#define CLASS(ID) class ID { /
public: /
ID(int) { out << #ID " constructor/n"; } /
~ID() { out << #ID " destructor/n"; } /
};
CLASS(Base1);
CLASS(Member1);
CLASS(Member2);
CLASS(Member3);
CLASS(Member4);
class Derived1 : public Base1 {
Member1 m1;
Member2 m2;
public:
Derived1(int) : m2(1), m1(2), Base1(3) {
out << "Derived1 constructor/n";
}
~Derived1() {
out << "Derived1 destructor/n";
}
};
class Derived2 : public Derived1 {
Member3 m3;
Member4 m4;
public:
Derived2() : m3(1), Derived1(2), m4(3) {
out << "Derived2 constructor/n";
}
~Derived2() {
out << "Derived2 destructor/n";
}
};
int main() {
Derived2 d2;
} ///:~
Base1 constructor
Member1 constructor
Member2 constructor
Derived1 constructor
Member3 constructor
Member4 constructor
Derived2 constructor
Derived2 destructor
Member4 destructor
Member3 destructor
Derived1 destructor
Member2 destructor
Member1 destructor
Base1 destructor
#ID中“#”是字符串连接符,即将其变成“ID”
ID非默认的构造函数,具备int参数但没有标识符,是强制在初始化列表中显式调用,没有标识符是为了防止编译报警。
基本原则是首先调用基类的构造函数,然后是成员对象的构造函数。析构的顺序正好相反,是为了防止可能的依赖关系。对于成员对象的构造函数的调用顺序,其不受初始化列表中的顺序影响,而只和成员对象在类中的定义顺序相关。否则可以有多种版本的构造,但析构只有一种。
该原则同样适用于拷贝构造函数,首先调用基类的拷贝构造函数,然后是自己的成员变量的构造