閱讀53 返回首頁    go 技術社區[雲棲]


C++對象模型(一):The Semantics of Constructors The Default Constructor (默認構造函數什麼時候會被創建出來)

本文是 Inside The C++ Object Model, Chapter 2的部分讀書筆記。

C++ Annotated Reference Manual中明確告訴我們: default constructor會在需要的時候被編譯器產生出來。注意,這裏是編譯器需要,而不是程序需要。後來的C++ Standard 95修改了這種說法,但是實質上仍是相同的: For class X, if there is none user declared constrator, one default constructor will be implicitly generated by the Compiler.

但實際上,如果default constructor是trivial(無用的),那麼編譯器根本就不會產生它!隻有一下四種情況,non-trivial default constructor會被產生出來,來保證C++語言的機製能夠按照預期工作:

  1)帶有Default Constructor的Member Class Object

      如果該class X 包含有帶有默認構造函數的成員class object (member object),那麼編譯器需要對此class X合成一個default constructor。不過該合成隻在該合成操作真正被調用時。

     被合成的這個default constructor,包含有調用這個member class的default constructor的代碼,但是它不會初始化它自身其他的成員變量,比如char *str; int data;這些成員變量的初始化時設計者的責任,而不是編譯器的職責!

   由此有進一步的思考,如果是設計者已經定義了constructor,來初始化比如char *str; int data; 那麼編譯器如何初始化其他的member class object呢? 答案就是編譯器需要擴張該class的constructor,以按照member class object的聲明順序來調用各個class的default constructor。


2) 帶有Default Constructor的Base Class

    如果class X繼承自一個帶有default constructor的class, 那麼編譯器將為這個class生成non-trivial的default constructor,並且按照base class的順序逐次調用。

   如果user declared 許多constructors,但是沒有default constructor(就是沒有任何參數的那個constructor),那麼編譯器不會產生default constructor了。而是擴張每個constructor,使其包含必要的default constructor的擴張代碼,比如初始化它的member class object。 參考第一種情況


3) 帶有virtual function

     對於有virtual function的class,一個virtual function table會被編譯器產生出來,存著virtual functions的地址。 而在每一個class的object中,會有一個pointer member(稱為vptr)會被編譯器生成出來,內容那個class virtual function table的地址。

   所以編譯器為了使得virtual function的機製生效,必須要為每個這種class的object生成合理的vptr,而vptr的賦值就發上在擴張後的constructors裏。如果class沒有任何的constructors,那麼default constructor會被認為是non-trivial並且會被生成。如果class有constructor/s,那麼所有的constructor都會擴張以賦予vptr以合理的值。


4)帶有一個virtual base class的class

    Virtual base class的實現在不同 的編譯器間有極大的差異。共同點就是virtual base class 在其每一個derived class object的位置,在執行期間能夠準備妥當。這些工作都要放到constructor中去完成。


總結
  在合成的default constructor中,隻有base class subobjects 和member class objects才會初始化。所有其他的nonstatic data member,都不會被初始化,這些工作應該由設計者(程序猿)而不是編譯器去完成。

最後更新:2017-04-03 12:53:36

  上一篇:go [LeetCode]104.Maximum Depth of Binary Tree
  下一篇:go 開源中國