C++對象模型學習筆記(二)--默認構造函數

    在文章開始以前,首先指出對於c++新手的兩個常見的誤解:javascript

   1、任何class若是沒有定義default constructor,就會被合成出一個來。java

   2、編譯器合成出來的default constructor會明確設定'「class內每個data member的默認值」c++

 

    首先咱們來討論第一個誤解。編譯器並非給任何一個沒有user-declared constructor的class合成出default constructor,編譯器只會在須要的時候纔會給沒有user-declared constructor的class合成出default constructor。那到底何時纔是須要的呢?首先咱們先看一下C++ standard中的一句話:「對於class X, 若是沒有任何user-declared constructor, 那麼會有一個default constructor被暗中(implicitly)聲明出來……一個被暗中聲明出來的default constructor將是一個trivial(無能的) constructor」。對於這句話,首先解釋一下,原話中的暗中聲明出來並不表明編譯器會給他合成出來,對於trivial constructor,編譯器是不會給他們合成出來的,編譯器會合成出來的只是那些nontrivial default construtor,而到底哪些纔算是nontrivial default constructor呢? 《Insider C++》中給出了四種狀況。程序員

    一、一個class的成員中含有帶有default constructor的member class object數組

      若是一個class中含有成員對象,並且這個對象有default constructor,, 那麼編譯器就會給這個class合成一個default constructor, 可是這個合成動做只有在調用須要時纔會產生。也就是說,在須要時纔會合成。ide

    例如:this

    

  
  
           
  
  
  1. class Foo{  
  2.     public Foo();  
  3.     ......  
  4. }  
  5.  
  6. class Bar{  
  7.     Foo foo;  
  8.     char *str  
  9. }  
  10.  
  11. void foo_bar(){  
  12.    Bar bar;   //bar必須在此初始化
  13.    if(str){}.....  

    在上述代碼中,line12,bar必須在此初始化,當這時時,編譯器就會給Bar合成一個default constructor,在default constructor中安插代碼調用Foo的default constructor,可是有一點,編譯器爲Bar合成的default constructor不會對str進行初始化,對str進行初始化,那只是程序員須要作的事情,而對於合成出的default constructor,它只知足編譯器的需求,而不會去知足程序的需求。spa

    若是class中內含一個以上的含有default constructor的object,那在爲class合成的default constructor中,會按照object的聲明次序調用object 的 default constructor。設計

  二、 class繼承於帶有default constructor的base class指針

    若是一個沒有任何constructor的派生類繼承自一個帶有default constructor的base class, 那麼這個派生類的default constructor被認爲是nontrivial,而對於nontrivial的default constructor, 編譯器會爲他合成出來。在合成出的default constructor中調用base class的default constuctor.

    若是設計者提供了多個constructor,但爲提供default constuctor,那編譯器不會合成新的default constructor,而是會擴展全部的現有的constructor,安插進去default constructor所必須的代碼。若是此類中仍存在第一種狀況,也就是說存在有menber object, 並且object含有default constructor, 那這些default constructor 也會被調用,在base class的default constructor被調用後。

  三、 這個class中帶有virtual function

    不管一個class是聲明(或繼承)了一個virtual function, 仍是派生自一個繼承串聯,其中有一個或多個virtual base class.無論上述哪一種狀況,因爲缺少由user聲明的constructor, 編譯器會詳細記錄合成一個default constructor的詳細信息。

    在編譯期間,會作如下的擴張工做:

   (1) 一個virtual function table會被編譯器產生出來,內含virtual functions的地址。

   (2) 編譯器會合成一個vptr, 插入每個object中。

    而合成出來的default constructor,固然會爲每個object 設定vptr的初值。

 

四、 帶有一個virtual base class的class

  對於這種狀況,我尚未研究透徹,研究透徹後我會再給你們貼出來。

以上就是對第一個誤解的討論,對於第二個誤解,對於合成出的default constructor,只會作一些必要的事情,好比對base class subobject 和member class object進行初始化,而對於一些其餘的nonstatic data member如整數,指針,數組等則不會進行初始化,由於那些東西對於編譯器來說並非必要的。

總結:

  以上給你們講述了那兩個誤解。但願可以對你們有所幫助。只有那四種狀況,編譯器纔會爲未聲明constructor的class合成出default constructor,並且被合成出來的constructor只會知足編譯器的須要,而不會去知足程序的須要,而他們之因此可以完成任務(知足編譯器的須要),是藉着調用"member object或base class的default constructor」或是「爲每個object初始化其virtual function機制(包括vtbl的建立和vptr的正確初始化)或virtual base class機制」。而對於沒有存在那四種狀況而且又沒有user-decleared constructor的class,咱們稱其擁有的是implict trivial default constructor, 而實際上,它並無被合成出來。

 

    因此,因而可知,以上的兩個誤解,都是錯的。

document.writeln(" 轉帖到人人網 轉帖到人人網<\/SPAN><\/a><\/div>");
相關文章
相關標籤/搜索