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

深度探索 C++ 對象模型(六):資料成員佈局、存取與虛擬繼承大小計算

     編輯:VC 教學

第三章探討資料成員綁定、佈局、存取,以及虛擬繼承下的類別大小計算,內容相對前兩章較易理解。

虛擬繼承下的類別大小

class X {};
class Y : public virtual X {};
class Z : public virtual X {};
class A : public Y, public Z {};

在某編譯器下:

  • sizeof(X) == 1(空類別插入一個 char 以確保唯一地址)
  • sizeof(Y) == 8、sizeof(Z) == 8
  • sizeof(A) == 12(而非想像中的 16)

大小組成分析

Y/Z 為 8 bytes:

  • 4 bytes:指向 virtual base class subobject 的指標
  • 1 byte:同 X 的 char
  • 3 bytes:alignment 填充

新式編譯器可能將空虛擬基類視為派生類開頭,省去 char 與填充,故 Y/Z 大小可能為 4。

A 為 12 bytes:

  • 4 bytes (Y 的 vptr) + 4 bytes (Z 的 vptr) + 1 byte (X 的 char) + 3 bytes 填充 = 12
  • 新式編譯器可能優化為 8 bytes

資料成員綁定:防禦性風格

嵌套類型聲明應放在 class 開頭,確保非直覺綁定正確性。範例:

typedef int length;
class Point3d {
public:
    void mumble(length val) { _val = val; } // length 解析為 global typedef int
    length mumble() { return _val; }
private:
    typedef float length; // 若放前面,上方引用將非法
    length _val;
};

資料成員佈局與存取

靜態成員

  • 視為全域變數,類生命週期內僅一實體。
  • 存取無額外空間/效率負擔,路徑直接。
  • 名稱衝突由編譯器演算法解決。

非靜態成員

透過隱含的 this 指標存取。編譯器將成員函數轉換:

// 原始
Point3d Point3d::translate(const Point3d& pt) {
    x += pt.x; y += pt.y; z += pt.z;
}
// 轉換後
Point3d Point3d::translate(Point3d* const this, const Point3d& pt) {
    this->x += pt.x; this->y += pt.y; this->z += pt.z;
}

非靜態成員存取:&origin._y == &origin + (&Point3d::_y - 1)。減 1 是為區分「指向第一個成員」與「不指向任何成員」的指標。

指向資料成員的指標

class Point3d {
public:
    virtual ~Point3d();
protected:
    static Point3d origin;
    float x, y, z;
};
&Point3d::z; // 值為 8 或 12 (視 vptr 位置),實際取值會 +1

+1 目的:區分空指標與指向第一個成員的指標。比喻:三室一廳,給共同朋友地址只給門牌號(不指向成員),給私人朋友才給房間號(需偏移量)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved