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

C++ 虛繼承構造函數機制:虛基類由最派生類初始化的強制規則與執行順序

     編輯:C++ 基礎

虛繼承構造核心規則

虛基類由最終最派生類直接初始化,而非由中間派生類初始化。這打破了普通繼承「只初始化直接基類」的規則。

菱形繼承實戰演示

#include <iostream>
using namespace std;

class A {  // 虛基類
public:
    A(int a) : m_a(a) { cout << "A(" << a << ")" << endl; }
protected:
    int m_a;
};

class B : virtual public A {  // 虛繼承
public:
    B(int a, int b) : A(a), m_b(b) { cout << "B(" << a << "," << b << ")" << endl; }
    void display() { cout << "m_a=" << m_a << ", m_b=" << m_b << endl; }
protected:
    int m_b;
};

class C : virtual public A {  // 虛繼承
public:
    C(int a, int c) : A(a), m_c(c) { cout << "C(" << a << "," << c << ")" << endl; }
    void display() { cout << "m_a=" << m_a << ", m_c=" << m_c << endl; }
protected:
    int m_c;
};

class D : public B, public C {  // 最終派生類
public:
    D(int a, int b, int c, int d) : A(a), B(90, b), C(100, c), m_d(d) {
        cout << "D(" << a << "," << b << "," << c << "," << d << ")" << endl;
    }
    void display() { cout << "m_a=" << m_a << ", m_b=" << m_b << ", m_c=" << m_c << ", m_d=" << m_d << endl; }
private:
    int m_d;
};

int main() {
    B b(10, 20); b.display();
    C c(30, 40); c.display();
    D d(50, 60, 70, 80); d.display();
}

運行結果與關鍵觀察

B(10,20)       // 直接建構 B 時,B 調用 A(10)
m_a=10, m_b=20
C(30,40)       // 直接建構 C 時,C 調用 A(30)
m_a=30, m_c=40
A(50)          // ★ D 建構時,最先調用 A(50) —— 虛基類由最派生類初始化
B(90,60)       // B 的 A(90) 被忽略
C(100,70)      // C 的 A(100) 被忽略
D(50,60,70,80)
m_a=50, m_b=60, m_c=70, m_d=80  // m_a 最終為 50,來自 D 直接調用 A(50)

為什麼強制最派生類初始化虛基類?

菱形繼承中 B 和 C 共享同一個 A 子物件。若分別初始化,參數衝突(B 傳 90,C 傳 100),編譯器無法決定採用哪個。C++ 規定:由最派生類 D 獨佔初始化權,中間類對虛基類構造函數的調用失效(但語法必須保留)。

構造函數執行順序:虛基類優先

無論初始化列表書寫順序,編譯器總是先構造虛基類,再按聲明順序構造其他基類:

// 即使寫成:
D(...) : B(90,b), C(100,c), A(a), m_d(d) { }
// 實際執行順序仍為:
// 1. A(a)      ← 虛基類最優先
// 2. B(90,b)   ← 按繼承聲明順序
// 3. C(100,c)
// 4. m_d(d)

普通繼承則嚴格按初始化列表順序執行。

直接/間接建構的差異

建構方式虛基類初始化者中間類 A() 調用
直接建構 B b(10,20)B (作為最派生類)生效
直接建構 C c(30,40)C (作為最派生類)生效
間接建構 D d(...)D (最終最派生類)失效 (被忽略)

析構順序:構造的完全逆序

  • 虛基類析構最後執行
  • 中間類按聲明逆序析構
  • 最派生類最先析構

總結核心心法

  1. 虛基類 = 共享子物件,必須由最終派生類統一初始化
  2. 中間類初始化列表保留 A()(語法要求),但實際失效
  3. 構造順序:虛基類 → 直接基類(聲明序) → 成員 → 自身
  4. 析構順序完全相反
  5. 虛繼承解決菱形重複,但引入構造複雜性——謹慎使用
  1. 上一篇文章:
  2. 下一篇文章:
  • --热点文章
  • Copyright © 程式碼之家 All Rights Reserved