首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Effective C++ 條款 43-44:多重繼承與理解 C++ 機制

     編輯:C++ 入門

條款 43:明智地使用多重繼承

核心問題:二義性

多重繼承時,若多個基類有同名成員,直接訪問會產生二義性。需顯式指定作用域:

class A { public: void f() {} };
class B { public: void f() {} };
class C : public A, public B {};
C c;
c.A::f();  // 必須指定
c.B::f();

虛函數二義性

  • 若基類有同名虛函數,派生類不重定義時,通過基類指針調用無二義性,但直接調用 c.f() 報錯。
  • 派生類重定義一次即可覆蓋所有基類同簽名虛函數(因派生類只能有一個同簽名函數)。
  • 若需分別保留基類不同實現並提供新介面,可引入中間類重命名:
class AuxA : public A { public: virtual void Afun() = 0; void fun() override { Afun(); } };
class AuxB : public B { public: virtual void Bfun() = 0; void fun() override { Bfun(); } };
class C : public AuxA, public AuxB {
    void Afun() override { cout << "A in C"; }
    void Bfun() override { cout << "B in C"; }
};

菱形繼承與虛基類

  • 菱形繼承導致基類多份拷貝。聲明 virtual 繼承可確保只有一份基類子對象。
  • 虛基類代價:對象佈局增加指針/偏移量,訪問虛基類成員間接,佔用更多空間/時間。
  • 庫設計者難以預知用戶是否會菱形繼承,故虛基類決策需極大遠見。

虛基類構造函數參數

  • 虛基類構造由最底層派生類直接調用(而非中間類傳遞)。
  • 新增中間類可能需修改最底層類的初始化列表。
  • 建議:虛基類不包含數據成員(如 Java interface),避免構造參數傳遞問題。

虛函數優先權規則

虛基類情況下,派生類中重定義的虛函數優先於基類原始定義,消除二義性:

class A { virtual void f() {} };
class B : virtual public A {};
class C : virtual public A { void f() override {} };
class D : public B, public C {};  // D::f() 解析為 C::f(),無二義性

多重繼承 vs 組合/單繼承重構

需共享功能時,優先考慮提取公共基類(單繼承菱形)而非多重繼承。多重繼承引入的復雜性(二義性、佈局開銷、構造順序)往往超過其便利性。

條款 44:說你想說的,理解你想說的

核心觀點:深入理解 C++ 對象模型語義,而非死記語法規則。例如:

  • 理解「拷貝構造」語義(值語義 vs 引用語義),而非只記「何時調用」。
  • 理解「虛函數表」機制,自然知曉為何構造/析構中調用虛函數不多態。
  • 理解「模板實例化」在編譯期生成代碼,而非運行期。

對 C++ 越深刻,設計決策越清晰,避坑能力越強。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved