子类(派生类)调用父类(基类)构造函数
在 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 直接继承基类构造函数:
通过合理使用初始化列表,可以精准控制基类构造函数的调用方式。
