深入C 建構函式

2021-06-14 10:22:46 字數 1501 閱讀 7048

通常很多c++程式設計師存在兩種誤解:

在讀《深度探索c++物件模型》之前,我一直停留在上述二種誤解上,所幸的是 lippman為我破除了藩籬。下面的部分我將隨《深度探索c++物件模型》對c++默 認建構函式一**竟。

c++標準規定:如果類的設計者並未為類定義任何建構函式,那麼會有乙個預設 建構函式被暗中生成,而這個暗中生成的預設建構函式通常是不做什麼事的(無 用的),下面四種情況除外。

換句話說,有以下四種情況編譯器必須為未宣告建構函式的類生成乙個會做點事 的預設建構函式。我們會看到這些預設建構函式僅「忠於編譯器」,而可能不會按 照程式設計師的意願程效命。

若乙個類x沒有定義任何建構函式,但卻包含乙個或以上定義有預設建構函式的 物件成員,此時編譯器會為x合成預設建構函式,該預設函式會呼叫物件成員的 預設建構函式為之初始化。如果物件的成員沒有定義預設建構函式,那麼編譯器 合成的預設建構函式將不會為之提供初始化。例如類a包含兩個資料成員物件, 分別為:string strchar *cstr,那麼編譯器生成的預設建構函式將只提 供對string型別成員的初始化,而不會提供對char*型別的初始化。

假如類x的設計者為x定義了預設的建構函式來完成對str的初始化,形如:a::a();因為預設建構函式已經定義,編譯器將不能再生成一 個預設建構函式。但是編譯器將會擴充程式設計師定義的預設建構函式——在最前面插 入對初始化str的**。若有多個定義有預設建構函式的成員物件,那麼這些成員 物件的預設建構函式的呼叫將依據宣告順序排列。

如果乙個沒有定義任何建構函式的類派生自帶有預設建構函式的基類,那麼編譯 器為它定義的預設建構函式,將按照宣告順序為之依次呼叫其基類的預設構造函 數。若該類沒有定義預設建構函式而定義了多個其他建構函式,那麼編譯器擴充 它的所有建構函式——加入必要的基類預設建構函式。另外,編譯器會將基類的默 認建構函式**加在物件成員的預設建構函式**之前。

帶有虛函式的類,與其它類不太一樣,因為它多了乙個vptr,而vptr的設定是由 編譯器完成的,因此編譯器會為類的每個建構函式新增**來完成對vptr的初始 化。

在這種情況下,編譯器要將虛基類在類中的位置準備妥當,提供支援虛基類的機 制。也就是說要在所有建構函式中加入實現前述功能的的**。沒有建構函式將 合成以完成上述工作。

總結:簡單來講編譯器會為建構函式做的一點事就是呼叫其基類或成員物件的默 認建構函式,以及初始化vprt以及準備虛基類的位置。

總的來說,編譯器將對建構函式動這些手腳:

【2011/12/21 補】需要說明的是,從概念來上來講,每乙個沒有定義建構函式 的類都會由編譯器來合成乙個預設建構函式,以使得可以定義乙個該類的物件, 但是預設建構函式是否真的會被合成,將視是否有需要而定。c++ standard 將 合成的預設建構函式分為 trivial 和 notrivial 兩種,前文所述的四種情況對 應於notrivial預設建構函式,其它情況都屬於trivial。對於乙個trivial預設 建構函式,編譯器的態度是,既然它全無用處,乾脆就不合成它。在這兒要釐清 的是概念與實現的差別,概念上追求縝密完善,在實現上則追求效率,可以不要 的東西就不要。

深入C 建構函式

通常很多c 程式設計師存在兩種誤解 在讀 深度探索c 物件模型 之前,我一直停留在上述二種誤解上,所幸的是lippman為我破除了藩籬。下面的部分我將隨 深度探索c 物件模型 對c 預設建構函式一 竟。c 標準規定 如果類的設計者並未為類定義任何建構函式,那麼會有乙個預設建構函式被暗中生成,而這個暗...

C 建構函式深入理解

01 初始化引數列表.cpp include include include using namespace std struct student 拷貝建構函式定義 拷貝建構函式的有效引數,必須是該類的物件的引用 if 1 student student s,int class no 1 else ...

深入探索建構函式

大致分為以下幾類 1 全預設引數初始化,不用傳參。2 半預設引數初始化,只需傳部分引數。3 無缺省引數初始化,定義多少個成員變數,傳多少個引數。4 使用初始化列表初始化,此類初始化更加高效,建議初始化的順序與宣告的順序相同。首先定義乙個日期類如下 class date 半預設引數 無缺省引數 初始化...