| 基類成員 | public 繼承 | protected 繼承 | private 繼承 |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | 不可見 | 不可見 | 不可見 |
鐵律:只有 public 繼承保持「is-a」關係,protected/private 繼承屬於「implemented-in-terms-of」(組合語義),極少使用。
編譯器僅在被使用時隱式生成。基類無默認構造 → 派生類必須顯式調用基類構造函數。
// 構造順序: // 1. 虛基類(由最派生類調用) // 2. 非虛基類(按繼承列表順序) // 3. 成員對象(按聲明順序) // 4. 派生類自身構造函數體 // 析構順序:完全相反 // 1. 派生類析構函數體 // 2. 成員對象(逆序) // 3. 非虛基類(逆序) // 4. 虛基類(逆序)
dynamic_cast 且有風險)nullptr 結尾。vptr 指向所屬類的虛表。class Base {
public:
Base() { foo(); } // 呼叫 Base::foo()
virtual void foo() { cout << "Base"; }
};
class Derived : public Base {
public:
Derived() { foo(); } // 呼叫 Derived::foo()
void foo() override { cout << "Derived"; }
};
原因:基類構造期間,vptr 指向 Base 虛表;派生類構造時,vptr 更新指向 Derived 虛表。構造/析構中虛函數調用靜態綁定,不發生多態。
| 函數類型 | 原因 |
|---|---|
| 構造函數 | 對象未完全構建,vptr 尚未初始化完成 |
| 拷貝構造 | 同構造函數 |
| 靜態成員函數 | 無 this 指針,無法訪問 vptr |
| 友元函數 | 非類成員,無 this |
析構函數必須 virtual(基類含虛函數時),否則 delete basePtr 僅調用基類析構 → 內存洩漏/資源未釋放。
class Interface {
public:
virtual void doIt() = 0; // 純虛函數
virtual ~Interface() {} // 虛析構
};
// Interface 不可實例化;子類必須實現 doIt() 才能實例化。
static 成員在整個繼承體系中僅一份實例,所有派生類共享。