天天看點

[讀書筆記] 深入探索C++對象模型-第三章 Data語義學(下)

整理第三章最後的部分内容,關于資料成員指針的,之前竟然沒聽過類資料成員指針一說,果然路漫漫其修遠兮啊。

注:以下例子和圖檔來源于原書。

1. 資料成員指針是指指向類資料成員的指針,其内容為對應資料成員在類對象中的偏移量,類型為A::*,例如,如下類:

class Point3d {
    public:
        virtual ~Point3d();
    protected:
        static Point3d origin;
        float x, y, z;
};
           

以下操作: &Point3d::z,将得到一個偏移值,其值最小為x和y大小的總和,或者是加上一個指針大小,這是因為類Point3d中存在虛函數,對應的類對象中就要有一個指向虛函數表的指針,該指針在類對象布局中,可能放在最前端,此時x,y,z的偏移分别為:4,8,12,也可能放在最末端,此時x,y,z的偏移分别為:0,4,8,然而實際取出來的值卻并非是這樣,這個值總是比實際大一,即1,5,9類似(在VS2015中測試并沒有大一,猜測是編譯器做了優化),之是以需要大一,是為了區分一個沒有指向任何資料成員的指針和一個指向了第一個資料成員的指針,例如:

float Point3d::*p1 = 0;
float Point3d::*p2 = &Point3d::x;
           

注意取非靜态資料成員的位址(靜态資料成員不屬于具體的類對象,故沒有偏移量一說)和取綁定與真正類對象身上的資料成員的位址的差別,Point3d origin; &origin.z類型為float*而不是Point3d::*,相應的靜态成員的類型也為float*。

指向資料成員的指針的使用方法:

float Point3d::*p2 = &Point3d::x;
Point3d point;
point.*p2 = 1//等價于point.x = 1
Point3d* p3d = &point;
p3d->*p2 = 2;//等價于p3d->x = 2
           

2. 多重繼承的情況下,将第二個(或者後繼)基類指針與一個和子類對象綁定的資料成員結合起來時,情況會變得複雜,例如:

[讀書筆記] 深入探索C++對象模型-第三章 Data語義學(下)

此種情況下,必須要考慮Base1存在導緻的Base2的偏移,注意判零:func1(bmp ? bmp + sizeof(Base1) : 0, pd );

第三章的内容整理完成,之後會繼續整理第四章的内容。

繼續閱讀