继承体系下的构造析构顺序
在C++继承层次中,派生类对象的构造和析构顺序是怎样规定的?基类构造函数和派生类构造函数的执行顺序如何?虚继承对构造析构顺序有什么特殊影响?
回答
我还是少年
构造顺序:
- 虚基类:按照继承声明中虚基类的出现顺序(深度优先从左到右)构造虚基类
- 非虚基类:按照继承声明中非虚基类的顺序(从左到右)构造
- 成员对象:按照类中声明的顺序构造
- 派生类自身的构造函数体:最后执行
struct A { A() { cout<<"A"; } };
struct B : virtual A { B() { cout<<"B"; } };
struct C : virtual A { C() { cout<<"C"; } };
struct D : B, C {
D() : A(), B(), C() { cout<<"D"; } // 实际A先构造一次
};
// 构造顺序: A -> B -> C -> D
析构顺序:是构造的严格逆序:
- 派生类析构函数体
- 成员对象析构(按声明逆序)
- 非虚基类析构(按继承声明逆序)
- 虚基类析构(按构造逆序)
虚继承的特殊性:
- 虚基类由最终派生类(most-derived class)负责构造——保证虚基类只被构造一次
- 中间基类对虚基类的初始化被忽略
- 虚基类的析构也由最终派生类触发
- 菱形继承(Diamond Inheritance)时虚基类只构造一次,否则多次构造
注意:构造函数的初始化列表顺序不影响实际构造顺序——实际顺序由编译器按上述规则决定,忽略初始化列表顺序。
常见错误:在派生类初始化列表中使用未构造的基类成员(因为基类尚未构造)。