C 建構函式語意學 預設建構函式

2022-09-24 02:39:09 字數 4380 閱讀 7460

在 class 中,若程式設計師沒有為該 class object 定義 default constructors,則編譯器會根據需要產生乙個 implicit default constructor,該 implicit default constructor 被認為是 trivial(無用的)。那編譯器怎樣才能產生乙個 nontrivial implicit default constructor?以下四個方面會產生nontrivial implicit default constructor:

1. class 中存在帶有 default constructor 的 member class object(成員物件);

2. class 繼承自帶有 default constructor 的 base class(基類);

3. 帶有乙個 virtual function 的 class;

4. 帶有乙個 virtual base class 的 class;

若乙個 class 中沒有定義任何 constructor,但是 class 中存在帶有 default constructor 的 member class object,則編譯器會在需要的時候合成乙個 nontrivial implicit default constructor;例如:

#include

using namespace std;

class foo

};

class bar ;

int main()

(gdb) s

the constructor of foo was exit.

main () at test.cpp:19

19 if(bar.x)

(gdb) s

21 cout<從除錯結果可以知道,執行bar bar語句時,編譯器會合成乙個barnontrivial implicit default constructor,合成的barnontrivial implicit default constructor 內含必要的**,能夠呼叫class foo的 default constructor 來處理 member class objectbar::foo,但是並不會產生**來初始化bar::x,將bar::foo初始化是編譯器所做的事,而初始化bar::x則是程式編寫者的事情;編譯器會合成乙個barnontrivial implicit default constructor 類似如下**所示:

inline bar::bar()

由於編譯器合成的barnontrivial implicit default constructor 並沒有對bar::x進行初始化,因此,被合成的 nontrivial implicit default constructor 只是滿足編譯器的需求,並不是程式設計師的需求,若要滿足程式設計師需求必須初始化bar::x,例如:

bar::bar()上面顯示的預設建構函式,編譯器同樣會初始化 member class objectfoo,即相當於:

bar::bar()

若class a內含乙個或乙個以上的 member class objects,則class a的每乙個 constructor 必須安裝宣告的順序呼叫每乙個 member classes 的 default constructor。例如:

#include

using namespace std;

class a

};

class b

};

class c

};

class d;

int main(void)

(gdb) s

class b

a::a (this=0xbffff039) at test.cpp:7

7 a()

(gdb) s

class a

c::c (this=0xbffff03a) at test.cpp:17

17 c()

(gdb) s

class c

main () at test.cpp:32

32 if(c.x)

(gdb) s

34 cout<若乙個沒有任何 constructors 的 class 繼承乙個帶有 default constructor 的 base class,那麼編譯器合成的 derived class 的 default constructor 也是 nontrivial 的,它將按照順序呼叫 base class 的 default constructor;

#include

using namespace std;

class baseclass

};

class foo

};

class bar: public baseclass ;

int main()

(gdb) s

base class

foo::foo (this=0xbffff038) at test.cpp:12

12 foo()

(gdb) s

class foo

main () at test.cpp:24

24 if(bar.x)

(gdb) s

26 cout << bar.x<當 class 內宣告或繼承乙個 virtual function,編譯器會根據需要合成乙個 nontrivial default constructor,在編譯期間會進行以下擴充:

編譯器產生乙個存放 class 的 virtual functions 位址的 virtual function table(vtbl);

在每乙個 class object 中,會存在乙個指向該 vtbl 的 pointer member(vptr);

編譯器會為每乙個 class 或其派生類 object 的 vptr 設定初值,放置適當的 virtual table 位址。

virtual base class 中的 data member 能夠通過 derived class object 進行讀取,同時 virtual base class 只有乙個例項,編譯器在合成 default constructor 時,每個derived class object 必須要記錄 virtual base class 位址的資訊,即每個 derived class object 儲存有指向 virtual base class 位址的指標。例如:

#include

using namespace std;

class x ;

class a: public virtual x ;

class b: public virtual x ;

class c: public virtual a, public virtual b ;

int main()

; (gdb) s

x::x (this=0xbffff034) at test.cpp:5

5 class x ;

(gdb) s

b::b (this=0xbffff038, __vtt_parm=0x8048c20 ,

__in_chrg=) at test.cpp:12

12 class b: public virtual x ;

(gdb) s

main () at test.cpp:19

19 a a;

(gdb) s

a::a (this=0xbffff00c, __in_chrg=, __vtt_parm=)

at test.cpp:10

10 class a: public virtual x ;

(gdb) s

x::x (this=0xbffff014) at test.cpp:5

5 class x ;

(gdb) s

x::x (this=0xbffff020) at test.cpp:5

5 class x {

(gdb) s

main () at test.cpp:22

22 cout a:0

26 cout b:0

28 return 0; 當 class 中沒有顯式宣告 default constructor,若是上述四種情況之一,編譯器會根據需要合成 nontrivial default constructor。但是編譯器不會初始化 class 中 nonstatic data member,只會初始化 base class subobjects 和 member class objects;

建構函式語意學

default建構函式操作 首先需要說明 帶來的第乙個問題,編譯器什麼時候合成預設建構函式 nontrivial 答案是編譯器需要的時候,而不是程式需要的時候。1 class foo class bar void foo bar 此時編譯器就會合成default 建構函式 類似 inline bar...

C 建構函式語義 預設建構函式

the c arm 告訴我們 預設建構函式會在需要的時候自動生成 被編譯器 然後 在需要的時候 是乙個很抽象的概念,本文主要描述的問題也正是這些需要的情況。我們看看下面的 片段 class foo void foo bar 使用者並沒有顯示地定義預設建構函式,編譯器會為它自動生成乙個無關緊要 tri...

建構函式之語意學

1 乙個類是不是一定有建構函式?c annotated referencemanual arm 建構函式只在需要的時候才會被編譯器產生出來。關鍵字 在需要的時候 被誰需要?一種是程式需要的時候,一種是變編譯器需要的時候。如果程式有需要 如,完成某些非靜態資料成員的初始化 那是程式設計師的責任,程式設...