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

C++ 多態深度解析(三):虛函數表在多重繼承中的內存佈局與手動打印技術

     編輯:關於C++

虛函數表打印通用技巧

利用對象首地址存放的 vptr(虛表指針),強轉為函數指針陣列即可遍歷調用:

using VTable = void(*)();  // 統一函數指針類型

void printVTable(void* obj) {
    int* vptr = *reinterpret_cast(obj);  // 取 vptr
    VTable* vtable = reinterpret_cast(vptr);
    int i = 0;
    while (vtable[i] != nullptr) {
        cout << "Func " << ++i << ": ";
        vtable[i]();  // 直接調用虛函數
        ++i;
    }
}

原理:32 位系統下,虛表是函數入口地址數組,以 nullptr 結尾。編譯器在編譯期生成只讀虛表,所有同類對象共享同一張表。

單繼承:虛表線性繼承與覆寫替換

class Base { virtual void f1(); virtual void f2(); virtual void f3(); };
class Derived : public Base { 
    void f1() override;  // 覆寫
    void f2() override;  // 覆寫
    virtual void f4();   // 新增
};

內存佈局:

  • Derived 對象首部仍是單一 vptr。
  • 虛表內容:[Derived::f1, Derived::f2, Base::f3, Derived::f4, nullptr] —— 覆寫函數替換對應槽位,新增函數追加在末尾。

多重繼承(無覆寫):多個 vptr 與多張虛表

class Base1 { virtual void f1(); virtual void f2(); virtual void f3(); };
class Base2 { virtual void f4(); virtual void f5(); virtual void f6(); };
class Derived : public Base1, public Base2 { virtual void f7(); };

對象佈局:

[Base1 vptr] → Base1 虛表
[Base1 數據]
[Base2 vptr] → Base2 虛表
[Base2 數據]
[Derived 數據]

Derived 擁有兩個 vptr,分別指向兩張獨立虛表。打印時需分別取 obj+0 和 obj+sizeof(Base1) 位置的 vptr。

多重繼承(有覆寫):同名虛函數雙重替換

class Base1 { virtual void f1(); virtual void f2(); virtual void f3(); };
class Base2 { virtual void f1(); virtual void f2(); virtual void f3(); virtual void f4(); };
class Derived : public Base1, public Base2 { 
    void f1() override;  // 同時覆寫 Base1::f1 和 Base2::f1
    void f4() override;  // 覆寫 Base2::f4
};

關鍵現象:Derived::f1 會同時替換兩張虛表中對應的 f1 槽位。這是編譯器為了保證「以 Base1* 或 Base2* 調用 f1 都能動態綁定到 Derived::f1」而生成的thunk(躍板碼)或直接填入同一地址。

虛繼承預告

菱形繼承引入 virtual 關鍵字後,虛表結構將出現 vbptr(虛基類指針)、共享虛基子物件 等更複雜機制,將在下一篇詳細剖析。

調試建議

  1. 用 __vfptr(MSVC)或 _vptr(GCC)在調試器中直接觀察虛表。
  2. 手動打印代碼僅供教學理解,生產環境嚴禁依賴佈局細節。
  3. 多重繼承時,動態轉型(dynamic_cast)依賴 RTTI 與虛表結構,理解佈局有助於診斷轉型失敗。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved