讀書筆記 《深度探索c 物件模型》 4

2021-08-26 16:05:06 字數 3616 閱讀 4741

讀書筆記 《深度探索c++物件模型》 (4)

2023年07月04日

第五章:構造,解構,拷貝語意學

5.2 繼承體系下的物件構造

a) 虛擬繼承

如同下面的繼承情況:#include #include using namespace std; class point virtual ~point() protected: float _x, _y; }; class point3d : public virtual point ~point3d() protected: float _z; }; class vertex : public virtual point ~vertex() protected: float _w; }; class vertex3d : public point3d, public vertex ~vertex3d() protected: float _u; }; int main () 在這種情況下,vertex3d壓制了它的兩個父類對point constructor的呼叫,這個呼叫工作由vertext3d本身來完成。所以輸出為:

b) vptr初始化語意學

接著上面的例子:#include #include using namespace std; class point virtual ~point() virtual void self() protected: float _x; }; class point3d : public virtual point ~point3d() void self() protected: //float _z; }; class vertex : public virtual point ~vertex() void self() protected: //float _w; }; class vertex3d : public point3d, public vertex ~vertex3d() void self() protected: //float _u; }; int main () 輸出為:

這說明,雖然new出來的是乙個vertex3d物件,但是在每個constructor中呼叫的self,既不是基類的self,也不是vertex3d的self,而都會被決議為是當前class的self。這個和vptr的初始化有關,因為vptr的初始化,是在base class constructor呼叫操作之後,在當前constructor執行或者當前constructor的member initialization list初始化之前。

乙個constructor的執行演算法如下:

1. 執行所有virtual base class以及上一層base class的constructor。

2. 初始化vptr。

3. member initialization list執行。

4. 執行constructor的**。

5.3 物件複製語意學

如果我們明確的想要拒絕把乙個class object指定給另乙個class object,那麼我們可以將copy assignment operator指定為private,並且不提供它的定義。

乙個class對於預設的copy assignment operator,在以下四種情況下不會出現bitwise copy語意:

1. 當class內帶乙個class object,其class帶有乙個copy assignment operator;

2. 當乙個class的base class有乙個copy assignment operator時;

3. 當乙個class宣告了任何的virtual functions時;(因此不必擔心vptr是否會被copy)

4. 當class繼承自乙個virtual base class時;

5.5 解構語意學

乙個destructor的執行演算法與constructor類似,但順序相反:

1. destructor函式本身首先被執行;

2. 如果class member帶有destructor,那麼它們會以宣告順序的相反順序被呼叫;

3. 如果乙個object帶有乙個vptr,那麼vptr被重新設定,指向適當的base class的virtual table;

4. 如果有直接的nonvirtual base class擁有destructor,那麼它們會以宣告順序的相反順序執行;

5. 如果有任何的virtual base class擁有destructor,而當前討論的這個class是最尾端的class(保證virtua base class的destructor只被呼叫一次),那麼它們會以其原來的構造順序的相反順序執行。

附:#include #include using namespace std; class point virtual ~point() protected: float _x; }; class point3d : public virtual point ~point3d() public: //int _z; }; class vertex : public virtual point ~vertex() protected: //float _w; }; class vertex3d : public point3d, public vertex ~vertex3d() protected: //float _u; }; int main ()

輸出的結果可以分析為:

class point有乙個4bytes的float member和乙個4bytes的vptr,該vptr中含有virtual destructor的位址;

class point3d有乙個4bytes的float member和兩個4bytes的vptr,其中乙個是繼承下來的,另外乙個含有virtua base class的offset;

class vertex同上;

class vertex3d有乙個8bytes的point,還分別有兩個4bytes的point3d和vertex;

但是,如果去掉point中的member:#include #include using namespace std; class point virtual ~point() protected: //float _x; //去掉 }; class point3d : public virtual point ~point3d() public: //int _z; }; class vertex : public virtual point ~vertex() protected: //float _w; }; class vertex3d : public point3d, public vertex ~vertex3d() protected: //float _u; }; int main () 輸出:

我的理解是:

class point有乙個4bytes的vptr,該vptr中含有virtual destructor的位址;

class point3d有乙個4bytes的float member,由於virtual base class沒有member,所以就沒有乙個vtable來存放virtual base class的offset,而point3d本身也沒有virtual function;

class vertex同上;

class vertex3d包含了乙個point3d和乙個vertex;

以上測試編譯環境為gcc。

讀書筆記 《深度探索c 物件模型》 (4)

第五章 構造,解構,拷貝語意學 5.2 繼承體系下的物件構造 a 虛擬繼承 如同下面的繼承情況 在這種情況下,vertex3d壓制了它的兩個父類對point constructor的呼叫,這個呼叫工作由vertext3d本身來完成。所以輸出為 b vptr初始化語意學 接著上面的例子 輸出為 雖然n...

《深度探索C 物件模型》讀書筆記(5)

純虛函式 在設計抽象基類時,需要注意以下幾點 1 不要將destructor宣告為pure virtual function 如果將destructor宣告為pure virtual function,則設計者一定得定義它。因為每乙個derived class destructor會被編譯器加以擴充...

《深度探索C 物件模型》讀書筆記(6)

物件的構造和解構 一般而言,我們會把object盡可能放置在使用它的那個程式區段附近,這樣做可以節省不必要的物件產生操作和銷毀操作。全域性物件 全域性物件的靜態初始化策略包括以下幾個步驟 1 為每乙個需要靜態初始化的物件產生乙個 sti 函式,內含必要的constructor呼叫操作或inline ...