本系列文章透過觀察物件記憶體佈局、追蹤組合語言碼,分析 C++ 物件模型、虛函數執行機制、虛擬繼承等核心主題。參考資料為 Lippman《深度探索 C++ 物件模型》(候捷譯),編譯器採用 VC7.1,結構對齊設為 1 位元組。
struct C000 {} 大小 1 位元組(佔位符),Debug 模式下內容為 0xCC。struct C010 { char c_; } 大小 1,內容為建構子初始值 0x01。struct C011 { char c1_, c2_; } 大小 2,內容 0x02 03。struct C012 {
static int sfoo();
int foo();
char c_;
static int i_;
};
大小仍為 1(未初始化為 0xCC)。驗證:普通成員函數、靜態成員函數、靜態資料成員均不出現在物件中。成員函數透過 this 指標關聯,靜態成員屬類別級別。
struct C014 : private C011 {}; // 大小 2,內容 02 03
struct C015 : public C010, private C011 {}; // 大小 3,內容 01 02 03
父類資料成員悉數被子類繼承,繼承存取指定符(public/private)僅影響「能見度」,不影響佈局。子類物件中繼承部分由父類建構子初始化。
struct C016 : C015 { int i_; };
大小 7 位元組(3 + 4),記憶體依序為 C010、C011、C016::i_。結論:普通繼承下,子類佈局為「父類資料成員 + 自身資料成員」,多層繼承「頂層在前」,多重繼承「最左父類在前」。