[C++]《深度探索C++物件模型》讀書筆記 – nontrivial default constructor

來源:互聯網
上載者:User

C++裡,如果程式員沒有顯式的定義預設建構函式(default constructor),編譯器會在需要的時候產生一個,也就是隱式地聲明出來。

隱式聲明的預設建構函式有兩種,一種是trivial(無用的) constructor,什麼都不做;另一種是nontrival constructor,編譯器合成的是後者。

在四種情況下,編譯器需要合成nontrival constructor:

1. 帶有"Default Constructor"的成員類對象

class A {public: A(), ... };class B {public: A a;};int f(){    B b;  //此處須調用B的預設建構函式}

因為B::a是一個member object,且其class A擁有default constructor,所以編譯器在需要調用B的預設建構函式時,會為B產生如下的預設建構函式

inline B::b(){    // C++偽碼    a.A::A();  // 調用a的預設建構函式}

但需要注意的是,編譯器產生的預設建構函式不會初始化基本類型的成員變數。
如果class B中有int類型的變數,其值不會被預設建構函式初始化為0。

還有一種情況,如果class B已經擁有一個預設建構函式,但其中並未對其對象成員進行初始化,如下例:

class B {public: A a, int num};B::B() {num = 0}

對於這種情況,編譯器會擴張已有的constructor,將對象成員的構造過程安插在user code前,像這樣:

B::B(){    a.A::A();     // 插入的compiler code    num = 0;      // user code}

 另外還需注意的是,編譯器所安插的代碼會按照“對象在class中的聲明順序”來調用各個constructor,在user code前。

2. "帶有Default Constructor"的Base Class

如果一個class派生自一個“帶有default constructor”的base class,那個這個class的default constructor需要被編譯器合成出來,以調用上一層base class的default constructor。
很多人都瞭解“子類在調用建構函式時,會先調用父類的建構函式”,這正是因為編譯器在我們定義的constructor中進行了上述擴充。

3. "帶有Virtual Function"的Class

虛函數表(vtbl)的相關實現機制超出了本文的範圍,讀者可找相關文章或書藉來學習。

如果class或繼承的base class中聲明了virtual function(虛函數),編譯器會對default constructor進行擴張:
  1. 為class產生一個virtual function table。
  2. 為每個class object建立一個額外的point member(vptr),指向相應的virtual function table。

此外,編譯器還會對“虛函數的叫用作業”進行修改,如b.f(),會被改為:

(*(b.vptr[1])) (&b);// 1表示函數f()在vtbl中的索引值,(b.vptr[1])返回了函數f()的地址。// &b表示交給f()函數調用的this指標,這裡涉及到了name magling的知識,讀者可自行搜尋。

4. "帶有一個Virtual Base Class"的Class

虛基類(virtual Base Class)指多繼承時,某個base class可能會出現在多個繼承路徑上。為了防止該基產生多個拷貝,可將基類的繼承聲明為虛擬,這樣就只會繼承基類的一份拷貝。

雖然這樣base class只有一份拷貝,但在多態環境下,編譯器無法固定”經由某個指標類型而存取的base class中的成員”的實際位移位置,因為其實際類型是可以改變的。
cfont對這個問題的解決方案是:在derived class object的每一個virtual base class中安插一個指標__vbcX,所有經由引用或指標對virtual base class的操作都可以通過該指標來完成。

而對__vbcX的初始化,正是編譯器在default constructor中進行的擴張。

 

對於這4種情況以外的,且沒有聲明default constructor的class,我們說它們擁有的是trivial default constructors,實際上它們並沒有被合成出來。
所以,“任何class如果沒有定義default constructor,都會被產生一個出來”這種說法是錯誤的。

最後還有一點要注意,產生出來的nontrivial default constructor只對類對象進行初始化,或基本類型(int, double, string)的成員變數還需要程式員來顯式的進行初始化。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.