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

C++ 虛函數表機制深度解析與 C 語言完整模擬實現

     編輯:C++ 入門

C++ 虛函數表 (vtable) 內存佈局與多態機制全景圖

虛函數是 C++ 多態的核心。本文通過 VS 調試器圖解,從單繼承到多重繼承、虛基類,系統剖析對象佈局、vptr 指向、vtable 共享、覆蓋替換、指針調整等細節,並給出 C 語言手動模擬完整代碼。

核心發現

  • 含虛函數的類對象首部隱含 vptr (void**),指向該類的唯一靜態 vtable(函數指針數組)。
  • 單繼承:派生類 vtable 接在基類 vtable 之後;覆蓋函數替換基類表對應槽位。
  • 多重繼承:按聲明順序排列基類子對象;第一個有虛函數的基類佔據對象首部,其 vtable 尾部追加派生類新虛函數;其他基類保持獨立 vtable,派生類對象內含多個 vptr。
  • 基類指針轉換涉及 `this` 指針偏移調整(`pb2 = pd1` 可能改變地址值)。

C 語言模擬關鍵結構

// 基類 1(有虛函數)
struct CBase1 { void** __vfptr; int base1_1; };
struct CBase1_VFTable { void (__stdcall* base1_fun1)(CBase1*); };

// 基類 2(無虛函數)
struct CBase2 { int base2_1; };

// 基類 3(有虛函數)
struct CBase3 { void** __vfptr; int base3_1; };
struct CBase3_VFTable { void (__stdcall* base3_fun1)(CBase3*); };

// 派生類:繼承順序 Base1, Base2, Base3
struct CDerive1 {
    CBase1 base1;
    CBase3 base3;  // 有虛函數的基類優先靠前
    CBase2 base2;
    int derive1_1;
};

// 合併 vtable:Base1 表尾部追加派生類虛函數
struct CBase1_CDerive1_VFTable {
    void (__stdcall* base1_fun1)(CBase1*);
    void (__stdcall* derive1_fun1)(CDerive1*);
};
// Base3 覆蓋表
struct CBase3_CDerive1_VFTable {
    void (__stdcall* base3_fun1)(CDerive1*);
};

手動構造對象與調用

// 全局 vtable 實例
CBase1_VFTable __vftable_base1 = { base1_fun1 };
CBase3_VFTable __vftable_base3 = { base3_fun1 };
CBase1_CDerive1_VFTable __vftable_base1_derive1 = { base1_fun1, derive1_fun1 };
CBase3_CDerive1_VFTable __vftable_base3_derive1 = { base3_derive1_fun1 };

// 構造派生對象
CDerive1 d1;
d1.base1.base1_1 = 11;
d1.base1.__vfptr = (void**)&__vftable_base1_derive1; // 指向合併表
d1.base3.base3_1 = 31;
d1.base3.__vfptr = (void**)&__vftable_base3_derive1; // 指向覆蓋表
d1.base2.base2_1 = 21;
d1.derive1_1 = 1;

// 手動計算基類指針偏移
char* p = (char*)&d1;
CBase1* pb1 = (CBase1*)(p + 0);
CBase3* pb3 = (CBase3*)(p + sizeof(CBase1));
CBase2* pb2 = (CBase2*)(p + sizeof(CBase1) + sizeof(CBase3));
CDerive1* pd1 = (CDerive1*)p;

// 調用:(*pb3->__vfptr[0])(pb3) 實現多態

總結

理解 vtable 機制有助於調試多態問題、優化性能、實現跨語言互操作。C++11 後仍沿用此 ABI(Itanium/MSVC)。

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