對C 預設建構函式的理解

2021-06-17 16:53:48 字數 3001 閱讀 9726

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

一、任何class如果沒有定義default constructor,就會被合成出乙個來。

二、編譯器合成出來的default constructor會明確設定'「class內每乙個data member的預設值」。

首先我們來討論第乙個誤解。編譯器並不是給任何乙個沒有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++》中給出了四種情況。

1、乙個class的成員中含有帶有default constructor的member class object

如果乙個class中含有成員物件,而且這個物件有default constructor,, 那麼編譯器就會給這個class合成乙個default constructor, 但是這個合成動作只有在呼叫需要時才會產生。也就是說,在需要時才會合成。

例如:[cpp]view plain

copy

class

foo    

class

bar    

void

foo_bar().....    

}   

在上述**中,bar必須在此初始化,當這時,編譯器就會給bar合成乙個default constructor,在default constructor中安插**呼叫foo的default constructor,但是有一點,編譯器為bar合成的default constructor不會對str進行初始化,對str進行初始化,那只是程式設計師需要做的事情,而對於合成出的default constructor,它只滿足編譯器的需求,而不會去滿足程式的需求。

如果class中內含乙個以上的含有default constructor的object,那在為class合成的default constructor中,會按照object的宣告次序呼叫object 的 default constructor。

2、 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被呼叫後。

3、 這個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的初值。

4、 帶有乙個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, 而實際上,它並沒有被合成出來。

所以,由此可見,以上的兩個誤解,都是錯的。

C 預設建構函式

c 預設建構函式 一直認為若程式設計師沒有自己定義無引數的建構函式,那麼編譯器會自動生成預設建構函式,來進行對成員函式的初始化,但這種認為是有誤的,不全面的.預設的建構函式分為有用的和無用的,所謂無用的預設建構函式就是乙個空函式 什麼操作也不做,而有用的預設建構函式是可以初始化成員的函式。對建構函式...

c 預設建構函式

c 什麼時候合成預設建構函式?c 合成的預設建構函式都做些什麼?以下三個條件同時滿足 源程式中沒有宣告任何建構函式 編譯器需要該類有預設建構函式 程式中需要呼叫預設建構函式 預設建構函式是以編譯單元為單位生成的 什麼時候編譯器需要預設建構函式 該類中有 有預設建構函式 的成員物件 該類繼承乙個有預設...

C 預設建構函式

先說c 新手一般的誤解 1.任何乙個類如果沒有定義預設建構函式,編譯器會自動合成乙個預設建構函式。2.編譯器合成出來的預設建構函式,會顯式的設定類中成員變數的值。先看乙個最基本的例子 從圖中可以看到物件a並沒有被初始化,即編譯器沒有為類a合成乙個預設建構函式。其實c 標準委員會曾敘述,如果沒有任何使...