struct C040 { virtual void foo() {} };
對象大小 4 字節(32 位),僅含 vptr 指向類級虛表。多個對象共享同一虛表,虛表條目指向實際函數代碼(通常經一條跳轉指令)。
struct C050 : C040 {}; // 未覆寫,共享虛表條目
struct C071 : C043 { virtual void foo1() {} } // 覆寫 foo1,虛表首項變更
驗證:基類與派生類虛表首項地址不同(覆寫),第二項相同(未覆寫)。
struct C041 { virtual void foo(); char c_; };
struct C042 { virtual void foo2(); char c_; };
struct C051 : public C041, public C042 {};
C051 大小 10 字節:[vptr1][C041::c_][vptr2][C042::c_]。兩個 vptr 分別指向各自的虛表,虛表條目繼承自對應基類。
為何不合併虛表?為了方便動態轉換時直接調整指針指向對應子對象起始位置,統一調用機制。
struct C082 : public C041, public C042 {
virtual void foo();
virtual void foo2();
virtual void foo3(); // 新增
char c_;
};
實驗證明:foo3 的地址出現在第一個虛表的繼承條目之後(索引 1),第二個虛表大小不變。調用 c082.foo3() 的匯編 call 0041D32F 對應第一虛表第二項。