子类(派生类)调用父类(基类)构造函数
在 C++ 中,子类(派生类)调用父类(基类)构造函数需要通过 成员初始化列表(member initializer list) 实现。
一、基本规则
- 隐式调用如果基类有 默认构造函数(无参构造),且派生类构造函数未显式调用基类构造函数,编译器会自动调用基类的默认构造函数。
- 显式调用如果基类 没有默认构造函数,或需要调用基类的 带参构造函数,必须在派生类构造函数的初始化列表中显式指定。
二、代码示例
场景 1:基类有默认构造函数
class Base { public: Base() { // 基类默认构造函数 cout << "Base默认构造" << endl; } }; class Derived : public Base { public: Derived() { // 隐式调用 Base() cout << "Derived构造" << endl; } }; int main() { Derived d; // 输出顺序:Base默认构造 → Derived构造 return 0; }
场景 2:基类无默认构造函数(必须显式调用)
class Base { public: Base(int x) { // 基类带参构造(没有默认构造) cout << "Base带参构造: x=" << x << endl; } }; class Derived : public Base { public: Derived(int y) : Base(y * 2) { // 显式调用 Base(int) cout << "Derived构造: y=" << y << endl; } }; int main() { Derived d(5); // 输出顺序:Base带参构造: x=10 → Derived构造: y=5 return 0; }
三、多继承与虚继承
多继承调用多个基类构造
class Base1 { public: Base1(int a) { cout << "Base1: a=" << a << endl; } }; class Base2 { public: Base2(double b) { cout << "Base2: b=" << b << endl; } }; class Derived : public Base1, public Base2 { public: Derived(int x, double y) : Base1(x), Base2(y) { // 显式调用两个基类构造 cout << "Derived构造" << endl; } }; int main() { Derived d(10, 3.14); // 输出顺序:Base1: a=10 → Base2: b=3.14 → Derived构造 return 0; }
虚继承(Virtual Inheritance)
class Base { public: Base(int x) { cout << "Base构造: x=" << x << endl; } }; class Derived : virtual public Base { // 虚继承 public: Derived(int a) : Base(a) { cout << "Derived构造" << endl; } }; class FurtherDerived : public Derived { public: FurtherDerived(int b) : Base(b + 10), // 虚基类构造必须由最底层派生类显式调用 Derived(b) { cout << "FurtherDerived构造" << endl; } }; int main() { FurtherDerived fd(5); // 输出顺序:Base构造: x=15 → Derived构造 → FurtherDerived构造 return 0; }
四、关键注意事项
- 初始化顺序基类构造函数总是先于派生类构造函数执行,且顺序由继承声明顺序决定(与初始化列表中的书写顺序无关)。
- 错误案例如果基类没有默认构造函数,且派生类未显式调用基类构造,将导致编译错误:
- C++11 继承构造函数使用 using Base::Base 直接继承基类构造函数:
通过合理使用初始化列表,可以精准控制基类构造函数的调用方式。