理解 C++ 對象在記憶體中的佈局,是掌握多態、繼承、虛繼承等核心機制的鑰匙。本文從單類虛函數表切入,層層遞進分析 9 種繼承場景的記憶體模型,配合圖解與 sizeof 實測,帶您窺探編譯器背後的佈局邏輯。
obj->vptr → vtbl[slot] → function address。測試環境:x86 Win32 Debug,指標 4 字節,double 8 字節。
template<typename T> class CPoint {
T _x, _y, _z;
virtual void setX(T); virtual void setY(T); virtual void setZ(T);
virtual T getX() const; virtual T getY() const; virtual T getZ() const;
};
// sizeof(CPoint<double>) = 32 bytes
// 佈局:[vptr(4)] [_x(8)] [_y(8)] [_z(8)] + 4字節對齊填充 = 32


template<typename T> class CPoint2D : public CPoint<T> { /* 無新虛函數 */ };
// sizeof(CPoint2D<double>) = 32,佈局與基類完全一致
// vptr 指向基類 vtbl(派生類共用基類虛表)


class CPoint2D : public CPoint {
virtual T getZ() const override { ... }
virtual void setZ(T) override { ... }
};
// sizeof 仍為 32
// vptr 指向「派生類專屬 vtbl」:前 4 槽繼承基類,後 2 槽被覆寫函數取代

class Base { int nCount; };
class Derived : virtual public Base { int nDeriveCount, nCurrentNum; };
// sizeof(Derived) = 14 bytes (預期 12 + 2? 實測 14)
// 佈局:[vbptr(4)] [Base::nCount(4)] [Derived::nDeriveCount(4)] [Derived::nCurrentNum(4)]
// vbptr 指向虛基類表,用於運行期找到共享的虛基類子對象偏移


本文僅展示前 4 種場景,剩餘 5 種(虛繼承+虛函數、多層虛繼承、多重繼承、菱形繼承等)佈局更為複雜,涉及 vbptr、vbtable、多 vptr、thunk 調整器 等機制,將在後續文章詳細拆解。
/d1 reportSingleClassLayout<ClassName> 編譯選項-fdump-class-hierarchy 或 -fdump-tree-originalprintf("%p\n", &obj) 配合風火輪調試器查看記憶體深入理解記憶體佈局,不僅能解釋 sizeof、切片問題、指標轉換行為,更是高效能 C++ 開發(如內存池、序列化、零拷貝)的基石。