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

C++ 物件記憶體佈局揭秘:單一繼承、多重繼承與虛函數表指標實測

     編輯:關於C++

C++ 標準僅規定「非靜態成員依宣告順序配置」,具體佈局由編譯器決定(ABI)。本文以 MSVC 6.0 為例,透過取址輸出與 Placement New 實驗,直觀展示單一繼承、多重繼承下的資料成員排列、vptr 位置與數量,助你理解物件模型本質。

實驗類別階層

class Point2d { public: int _x, _y; virtual void f() {} };           // 1 vptr
class Point3d : public Point2d { public: int _z; };                  // 單繼承
class Vertex { public: int next; virtual void h() {} };              // 1 vptr
class Vertex3d : public Point3d, public Vertex { public: int mumble; }; // 多重繼承

MSVC 6.0 實測輸出

&v3d      = 0x0012ff64  ← Vertex3d 起始位址 = Point3d 子物件 = Point2d 子物件
&_x      = 0x0012ff68  ← Point2d::_x
&_y      = 0x0012ff6c  ← Point2d::_y
&_z      = 0x0012ff70  ← Point3d::_z
&pv      = 0x0012ff74  ← Vertex 子物件起始 = 第二個 vptr
&next    = 0x0012ff78  ← Vertex::next
&mumble  = 0x0012ff7c  ← Vertex3d::mumble

記憶體佈局圖解

Vertex3d (sizeof = 28 bytes)
├── Point2d 子物件 (offset 0)
│   ├── vptr #1 → Point2d vtable
│   ├── _x (4)
│   └── _y (4)
├── Point3d 擴充 (offset 12)
│   └── _z (4)
├── Vertex 子物件 (offset 16)
│   ├── vptr #2 → Vertex vtable
│   └── next (4)
└── Vertex3d 自身 (offset 24)
    └── mumble (4)

關鍵觀察

  • 多重繼承 = 多個子物件 = 多個 vptr:每個帶有虛函數的基類子物件擁有自己的 vptr。
  • 基類順序決定子物件順序:class D : public B1, public B2 → B1 在低位址,B2 緊隨其後。
  • 衍生類新增成員置於最後:mumble 排在所有基類子物件之後。
  • 指標轉型調整位址:Vertex* pv = &v3d 時,編譯器自動加上 offsetof(Vertex3d, Vertex) (16 bytes)。

Placement New 驗證技巧

long storage[30];
Vertex3d* p = new (storage) Vertex3d; // 在陣列上建構物件
for (int i=0; i

現代編譯器差異提醒

  • Itanium ABI (GCC/Clang/Linux):主物件只有一個 vptr,次要基類用 vtable offset 方式,佈局不同。
  • MSVC x64:vptr 8 位元組,對齊規則更嚴格。
  • 標準不保證佈局,僅保證「標準配置類別」的相容性;跨 DLL/語言邊界請用 C 風格介面或 std::byte 序列化。
「理解物件佈局不是為了鑽標準漏洞,而是為了除錯多重繼承切割、效能分析快取命中、以及與 C/組語互操作時的底氣。」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved