三個重要函式:建構函式,析構函式,拷貝建構函式。
1. 無繼承情況下的物件構造。
當類中存在虛函式時,編譯器會對該類產生膨脹作用,
例如如下類:
[cpp]
view plain
copy
class
point
virtual
float
z();
protected
: float
_x, _y;
};
a. 我們所定義的建構函式中,會被附加一些**,一邊初始化虛表指標(vptr),這些**會安插在任何基類建構函式的呼叫之後,但必須在任何使用者**的**之前,一種可能的上述point類的建構函式擴充套件:
[cpp]
view plain
copy
point* point::point (point*
this
, float
x, float
y)
: _x(x), _y(y)
b. 合成乙個拷貝構造和拷貝賦值函式,這兩個函式是重要的,會被呼叫的,用來在這兩個函式被呼叫時,設定虛表指標等操作,可能的擴充套件結果:
[cpp]
view plain
copy
//copy constructor
inline
point* point::point (point*
this
, const
point& rhs)
2. 繼承情況下的物件構造。
當我們定義乙個類物件時:t object,建構函式可能會發生擴充套件:
a. 初始化列表中資料成員初始化操作會放入建構函式本身,注意是以資料成員在類中的宣告順序,而非在初始化類表中的順序。
b. 如果有某乙個資料成員未出現在初始化列表中,但是他有預設建構函式,則該預設建構函式會被呼叫。
c. 在那之前,如果如果類該物件有虛表指標,它(們)會設定初值,指向適當的虛表(們)。
d. 在那之前,所有基類建構函式會被呼叫,按照它們在子類中的繼承順序:
i. 如果基類在初始化列表中,任何明確指定的引數都需要傳遞進去。
ii. 如果基類沒有列於初始化列表,那麼會呼叫可能存在的預設建構函式。
iii. 如果基類是多重繼承下的第二個或者後繼,那麼此時子類的this指標需要被調整,以指向該基類部分(subobject)。
e. 在那之前,所有虛基類的建構函式必須被呼叫, 從左到右,從最深到最淺。
i. 如果基類在初始化列表中,任何明確指定的引數都需要傳遞進去,
如果沒有,會呼叫可能存在的預設建構函式。
ii. 類中每乙個虛基類子物件的偏移(offset)必須在執行期可被訪問。
iii. 如果類物件是最底層的(most-derived),其建構函式可能會被呼叫,某些支援這個行為的機制會被放入(下文提到的__most_derived)。
繼續以point為例,進行一下擴充,並宣告line類:
第二個建構函式會被擴充套件為:
析構函式會被擴充套件為:
虛擬繼承情況下,子類建構函式的擴充套件有些不一樣,考慮如下類以及其繼承體系:
由於虛基類在子類中只有乙份,所以虛基類point的建構函式只能被呼叫一次,例如,在例項化point3d或者vertex物件時,作為二者直接基類的point的建構函式需要呼叫,但是在定義vertex3d物件時,會呼叫point3d和vertex的建構函式,此時二者的構造不應該呼叫point的建構函式,因為point已經在vertex3d建構函式中呼叫過了,為了保證虛基類的唯一性,不允許再呼叫,也就是只有最下層的子類建構函式中需要呼叫虛基類的建構函式,point3d的建構函式以及vertex3d的建構函式的可能擴充套件如下,注意紅框
中的內容:
在vertex3d建構函式中,當呼叫其父類point3d以及vertex的建構函式時,__most_derived引數會設定為false,已壓制而這對於point的再次初始化:
3. 關於虛表指標的初始化在子類建構函式中的情況。
a. 子類建構函式中,所有虛基類以及基類的建構函式會被呼叫。
b. 接著是物件的虛表指標被初始化,指向相關的虛表。
c. 在建構函式內展開可能存在的資料成員初始化列表,由於此時可能有虛函式呼叫,所以該步必須在虛表指標初始化妥當之後。
d. 最後,指向我們碼農提供的**。
例如,之前例子中的pvertex類的某個建構函式如下:
可能會被擴充套件成為,下圖貌似有一點遺漏,this->vertex3d::vertex3d(x, y, z)應該是:this->vertex3d::vertex3d(false
, x, y, z)以防止虛基類多次構造。
深入探索C 物件模型
深入探索c 物件模型 本書目錄結構如下 第1章 關於物件 object lessons 加上封裝後的布局成本 layout costs for adding encapsulation 1.1 c 模式模式 the c object model 簡單物件模型 a object model 驅動物件模...
深入探索C 物件模型之物件
物件 一 在c語言中,資料 和 對資料的處理 函式 分開宣告的,也就是說,語言本身並沒有支援 資料和函式 之間的關聯性。例如,typedef struct point3dpoint3d 而在c 中,座標型別和座標數目都可以引數化 template class point type operator ...
深入探索C 物件模型(6)
物件陣列的構造 物件資料的構造一般有兩種方式 靜態和動態 1 靜態分配 以string類為例,string a 10 就是以靜態形式構造資料,這樣的陣列的個數是確定的不能修改的。像這樣的陣列怎麼進行構造和析構呢?編譯器在構造陣列的時候會生成乙個使用預設建構函式的陣列建構函式arr new char ...