核心規則
- 構造順序:基類 → 成員對象(按聲明順序) → 派生類自身
- 析構順序:完全相反,派生類 → 成員對象(逆聲明順序) → 基類
代碼演示
#include
using namespace std;
class Base {
float x, y;
public:
Base(float a, float b) : x(a), y(b) {
cout << "基類構造函數被調用\n";
cout << "x=" << x << " y=" << y << endl;
}
~Base() { cout << "基類析構函數被調用\n"; }
};
class Derived : public Base {
float z, q;
public:
// 初始化列表調用基類構造函數
Derived(float a, float b, float c, float d) : Base(a, b), z(c), q(d) {
cout << "派生類構造函數被調用\n";
cout << "z=" << z << " q=" << q << endl;
}
~Derived() { cout << "派生類析構函數被調用\n"; }
};
int main() {
cout << "=== 創建 Derived 對象 ===\n";
Derived d(1.1, 2.2, 3.3, 4.4);
cout << "=== 對象銷毀 ===\n";
return 0;
}
輸出結果
=== 創建 Derived 對象 ===
基類構造函數被調用
x=1.1 y=2.2
派生類構造函數被調用
z=3.3 q=4.4
=== 對象銷毀 ===
派生類析構函數被調用
基類析構函數被調用
關鍵點解析
| 階段 | 順序 | 說明 |
| 構造 | 1. Base(a,b) | 初始化列表顯式調用基類構造 |
| 2. z(c), q(d) | 成員對象按聲明順序初始化 |
| 3. Derived 體 | 派生類構造函數體執行 |
| 析構 | 1. ~Derived() | 派生類析構函數體執行 |
| 2. ~z, ~q | 成員對象逆序析構 |
| 3. ~Base() | 基類析構函數體執行 |
常見錯誤
- 忘記在初始化列表調用基類構造函數(基類無默認構造時編譯錯誤)
- 派生類構造函數體中賦值基類私有成員(不可訪問,必須通過基類構造)
- 虛繼承時虛基類由最派生類直接構造,順序調整為:虛基類 → 非虛基類 → 成員 → 派生類
虛繼承特殊順序
class VBase { VBase() { cout << "VBase\n"; } };
class B1 : virtual public VBase { B1() { cout << "B1\n"; } };
class B2 : virtual public VBase { B2() { cout << "B2\n"; } };
class D : public B1, public B2 { D() { cout << "D\n"; } };
// 輸出:VBase → B1 → B2 → D