早期 C++ 編譯器(CFront)對 inline 成員函數的主體延遲到類定義結束才解析。導致:
extern float x;
class Point3d {
float X() const { return x; } // 綁定到全域 x,而非成員 x!
float x, y, z;
};
為規避此問題,形成兩種防禦風格:
C++ Standard 規定:inline 成員函數主體在類定義完整出現後才分析。因此上例中 X() 正確綁定到成員 x。
但若寫成:
extern int x;
class Point3d {
float X() const { return x; } // 仍綁定全域 x,因類內尚未聲明成員 x
private:
float x;
};
雖然標準保證「類定義完成後分析」,但名稱查找仍遵循「先查內部作用域,再查外層」,此時類內無 x,故綁定全域。最佳實踐:數據成員儘量前置。
access section(public/private/protected 塊)內,成員按聲明順序佈局,較晚聲明者地址較高。標準允許編譯器將不同 access section 的成員自由重排,不保證聲明順序。但主流編譯器(MSVC, GCC, Clang)均按聲明順序連續佈局,section 間無額外開銷。
virtual 函數的類,編譯器在對象中插入 vptr 指向虛函數表。template
char* access_order(D1 C::*m1, D2 C::*m2) {
return (m1 < m2) ? "member 1 first" : "member 2 first";
}
// 用法:access_order(&Point3d::z, &Point3d::y);
利用成員指針比較大小可在運行期檢測佈局順序(需關閉優化)。
成員綁定現遵循「類定義完成後分析」,但名稱查找仍依賴聲明位置;成員佈局在同 section 內保證聲明順序,section 間及 vptr 位置由編譯器決定。理解這些規則有助於編寫可移植、高效的 C++ 代碼,並能解讀對象內存佈局相關的底層問題。