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

C++ 虛基類詳解:解決菱形繼承的二義性問題

     編輯:C++ 入門

什麼是虛基類?

在 C++ 多重繼承中,當一個派生類通過多條路徑繼承自同一個基類時,會導致基類成員在派生類中出現多份拷貝,造成二義性。例如經典的「菱形繼承」結構:類 A 是基類,B 和 C 分別繼承 A,D 再繼承 B 和 C。此時 D 會包含兩份 A 的成員,直接訪問會報錯。

解決方案有二:

  • 若二義性發生在直接基類,可用類作用域(如 Base::member)顯式指定。
  • 若二義性發生在間接基類(如上述 A),必須使用虛基類機制。

虛基類的聲明與作用

語法:

class Derived : virtual 存取指定符 Base { ... };

關鍵點:

  • virtual 關鍵字出現在派生類定義中,而非基類。
  • 將基類聲明為虛基類後,無論有多少派生類,整個繼承體系中只會存在一份基類子物件,所有派生類共用這一份。
  • 強制要求:沿著繼承鏈的每一個直接派生類都必須加 virtual,否則未加者仍會產生獨立副本。

虛基類的建構與解構順序

規則較一般繼承複雜,核心原則:

  1. 虛基類優先於非虛基類建構。
  2. 同層級多個虛基類,按繼承聲明順序建構。
  3. 虛基類全程只建構一次(由最底層的具體派生類負責調用)。
  4. 若虛基類本身是非虛繼承而來,則先建構其非虛基類部分。
  5. 解構順序嚴格相反。

範例分析

class Base1 { public: Base1() { cout << "Base1"; } };
class Base2 { public: Base2() { cout << "Base2"; } };
class Level1 : public Base2, virtual public Base1 { ... };
class Level2 : public Base2, virtual public Base1 { ... };
class TopLevel : public Level1, virtual public Level2 { ... };

建構 TopLevel obj 時輸出順序:

Base1 → Base2 → Level2 → Base2 → Level1 → TopLevel

解析:TopLevel 先建構虛基類 Level2,Level2 又先建構其虛基類 Base1,再建構非虛基類 Base2,最後建構自己。接著 TopLevel 建構非虛基類 Level1,此時 Base1 已建構過跳過,直接建構 Base2 和 Level1,最後建構 TopLevel 自身。

帶參數的虛基類建構

若虛基類有帶參數的建構函式,最底層的派生類必須在初始化列表中直接調用虛基類的建構函式,中間層派生類雖也要在初始化列表中列出,但實際參數以最底層派生類傳遞的為準。

class A { public: A(char c) { ... } };
class B : virtual public A { public: B(char i, char j) : A(i) { ... } };
class C : virtual public A { public: C(char i, char j) : A(i) { ... } }; // 必須寫上 :A(i) 即使不會被使用
class D : public B, public C {
public:
    D(char i, char j, char k, char l, char m, char n)
        : C(k,l), B(i,j), A(n) { ... } // 這裡的 A(n) 決定最終參數
};

輸出顯示 A 先用 n 建構,其後 B、C 使用各自參數建構,最後 D 自身。注意 C 的初始化列表雖寫 :A(i) 但實際被忽略。

總結:建構/解構調用順序速查

  1. 所有虛基類,按繼承順序建構(只一次)。
  2. 所有非虛基類,按繼承順序建構。
  3. 所有成員子物件,按聲明順序建構。
  4. 派生類自身建構函式執行。
  5. 初始化列表中虛基類優先於非虛基類;同層虛基類按聲明順序,非虛基類按繼承順序。

虛基類的指標/引用相容性

  • 派生類物件地址可隱式轉換為虛基類指標。
  • 虛基類引用可綁定至派生類物件。
  • 本質:「大」轉「小」(派生類包含基類),符合多型基本規則。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved