class D : public A, private B, protected C {
// D 新增成員
};
D 獲取所有基類成員,訪問權限受繼承方式限制D(int a, int b, int c, int d, int e)
: BaseA(a, b), BaseB(c, d), m_e(e) { // 調用多個基類構造
cout << "Derived constructor" << endl;
}
與初始化列表書寫順序無關:
class D : public BaseA, public BaseB { ... }; // 聲明序:BaseA → BaseB
// 即使寫成:
D(...) : BaseB(c,d), BaseA(a,b), m_e(e) { }
// 實際執行仍為:
// 1. BaseA(a,b)
// 2. BaseB(c,d)
// 3. m_e(e)
// 4. Derived 函數體
#include <iostream>
using namespace std;
class BaseA {
public:
BaseA(int a, int b) : m_a(a), m_b(b) { cout << "BaseA constructor" << endl; }
~BaseA() { cout << "BaseA destructor" << endl; }
void show() { cout << "m_a=" << m_a << ", m_b=" << m_b << endl; }
protected: int m_a, m_b;
};
class BaseB {
public:
BaseB(int c, int d) : m_c(c), m_d(d) { cout << "BaseB constructor" << endl; }
~BaseB() { cout << "BaseB destructor" << endl; }
void show() { cout << "m_c=" << m_c << ", m_d=" << m_d << endl; }
protected: int m_c, m_d;
};
class Derived : public BaseA, public BaseB {
public:
Derived(int a, int b, int c, int d, int e)
: BaseA(a, b), BaseB(c, d), m_e(e) { cout << "Derived constructor" << endl; }
~Derived() { cout << "Derived destructor" << endl; }
void display() {
BaseA::show(); // 顯式指定調用哪個 show()
BaseB::show();
cout << "m_e=" << m_e << endl;
}
private: int m_e;
};
int main() {
Derived obj(1,2,3,4,5);
obj.display();
}
BaseA constructor BaseB constructor Derived constructor m_a=1, m_b=2 m_c=3, m_d=4 m_e=5 Derived destructor BaseB destructor BaseA destructor
觀察:構造順序遵循聲明序,析構順序完全相反。
多基類有同名成員時,直接訪問導致歧義:
class Derived : public BaseA, public BaseB {
void display() {
// show(); // 錯誤:歧義
BaseA::show(); // 正確:顯式指定
BaseB::show();
}
};
使用 基類名::成員名 消除歧義。
Derived 物件: +------------------+ ← Derived*, BaseA* (首基類,地址同) | BaseA 部分 | | m_a, m_b | +------------------+ ← BaseB* (偏移量 > 0) | BaseB 部分 | | m_c, m_d | +------------------+ | Derived 部分 | | m_e | +------------------+
Derived* → BaseB* 需指針調整| 爭議點 | 說明 |
|---|---|
| 複雜度 | 菱形衝突、指針調整、構造/析構順序、虛函數表多重性 |
| 語義模糊 | 「是一種」關係難以同時滿足多個基類 |
| 語言演進 | Java/C#/PHP/Rust/Go 等現代語言移除多重繼承,改用介面 |
class D { A a; B b; } 而非 class D : A, B多重繼承語法簡單(逗號分隔基類),但語義與實現極其複雜:構造順序遵循聲明序、首基類零偏移、命名衝突需顯式消歧、析構逆序。現代 C++ 實務強烈不推薦使用,Java/C# 等語言已移除。掌握其機制是為了讀懂舊代碼(如標準庫 iostream),新代碼請優先選擇組合、介面、策略模式。