繼承是 C++ 面向對象程式設計實現代碼復用的核心機制。它允許在保留基類(父類)原有特性的基礎上,擴展新功能產生派生類(子類)。這種機制建立了類之間的層次關係,體現了從一般到特殊的認知邏輯。
| 繼承方式 | 基類 public 成員 | 基類 protected 成員 | 基類 private 成員 | 派生類對象訪問基類 public 成員 |
|---|---|---|---|---|
| public(公有繼承) | public | protected | 不可見 | 可訪問 |
| protected(保護繼承) | protected | protected | 不可見 | 不可訪問 |
| private(私有繼承) | private | private | 不可見 | 不可訪問 |
核心規則:基類的 private 成員在派生類中永遠不可見(不可直接訪問),只能通過基類的 public/protected 介面間接操作。
class Base {
public:
Base() : _pri(1), _pro(2), _pub(3) {}
int _pub;
protected:
int _pro;
private:
int _pri;
};
// 公有繼承:is-a 關係
class DerivedPublic : public Base {
public:
void show() {
_pub = 10; // ✓ 仍為 public
_pro = 20; // ✓ 仍為 protected
// _pri = 30; // ✗ 編譯錯誤:基類 private 不可見
}
};
// 保護繼承
class DerivedProtected : protected Base {
public:
void show() {
_pub = 10; // ✓ 變為 protected
_pro = 20; // ✓ 仍為 protected
}
};
// 私有繼承:has-a 關係(實現細節)
class DerivedPrivate : private Base {
public:
void show() {
_pub = 10; // ✓ 變為 private
_pro = 20; // ✓ 變為 private
}
};
void testAccess() {
DerivedPublic d1;
d1._pub = 100; // ✓ 派生類對象可訪問基類 public 成員
DerivedProtected d2;
// d2._pub = 100; // ✗ 編譯錯誤:基類 public 已變為 protected
DerivedPrivate d3;
// d3._pub = 100; // ✗ 編譯錯誤:基類 public 已變為 private
}
Base base; DerivedPublic derived; base = derived; // ✓ 合法:派生類對象賦值給基類對象(發生對象切片) // derived = base; // ✗ 非法:基類對象無法賦值給派生類對象(缺少派生類特有成員)
對象切片:派生類對象賦值給基類對象時,只有基類部分被複製,派生類特有的成員被「切掉」。這是為什麼多態必須使用指標或引用的原因。
class Base1 { public: Base1() { cout << "Base1 建構\n"; } ~Base1() { cout << "Base1 解構\n"; } };
class Base2 { public: Base2() { cout << "Base2 建構\n"; } ~Base2() { cout << "Base2 解構\n"; } };
class Derived : public Base1, public Base2 {
public:
Derived() { cout << "Derived 建構\n"; }
~Derived() { cout << "Derived 解構\n"; }
};
建構順序:Base1 → Base2 → Derived(按繼承聲明順序)
解構順序:Derived → Base2 → Base1(與建構順序完全相反)
// 菱形繼承問題
class Base { public: int _a; };
class Derived1 : public Base { };
class Derived2 : public Base { };
class Final : public Derived1, public Derived2 { }; // 包含兩份 Base::_a
// 虛繼承解決方案
class VBase { public: int _a; };
class VDerived1 : virtual public VBase { };
class VDerived2 : virtual public VBase { };
class VFinal : public VDerived1, public VDerived2 { }; // 僅包含一份 VBase::_a
class Base {
public:
Base(int x) : _x(x) { cout << "Base(" << x << ")\n"; }
virtual ~Base() { cout << "~Base()\n"; } // 虛解構函數:多態刪除必須
private:
int _x;
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x), _y(y) { cout << "Derived(" << y << ")\n"; }
~Derived() { cout << "~Derived()\n"; }
private:
int _y;
};
virtualC++ 繼承機制強大但複雜。掌握三種繼承方式的訪問控制語義、理解對象切片與多態的關係、熟悉菱形繼承與虛繼承的內存模型、遵循建構/析構順序規則,是寫出健壯、可維護 C++ 代碼的關鍵。實際開發中,優先考慮 public 繼承表達介面契約,組合優於私有繼承,謹慎使用多重繼承並善用虛繼承解決菱形問題。