什麼情況下C 編譯器會生成預設的建構函式

2021-08-08 11:35:03 字數 1430 閱讀 6176

問題:對c++初學者來說存在乙個誤區,如果類沒有定義任何建構函式,編譯器會自動生成預設的建構函式。

注意:這種說法是錯誤的。

正確的說法:惟有預設建構函式」被需要「的時候編譯器才會合成預設建構函式。

那什麼情況下是「被需要」的時候?

以下有四種情況編譯器會自動合成預設建構函式

情況1 

含有類物件資料成員,該類物件型別有預設建構函式

即:乙個class含有類物件資料成員,該類物件型別有預設建構函式

sa包含了乙個物件成員objectb,而這個物件成員定義了(classb的)預設建構函式,那麼編譯器會為classa合成乙個預設建構函式。

class a

};class b

;void test()

int main()

原因:

因為類成員物件有預設建構函式,那麼編譯器就需要

顯式的來呼叫這個類成員物件的

建構函式。而編譯器想顯式的呼叫類成員物件的預設建構函式,就需要自己來合成一些**來呼叫。但是記住,編譯器合成的預設建構函式

僅僅呼叫類成員物件的預設建構函式,而不對我們類裡面的其它變數做任何初始化操作。

情形2 

基類帶有預設建構函式的派生類

當乙個類派生自乙個含有預設建構函式的基類時,該類也符合編譯器需要合成預設建構函式的條件。編譯器合成的預設建構函式將根據基類宣告順序呼叫上層的基類預設建構函式。

原因:因為派生類被合成時需要顯式呼叫基類的預設建構函式。

class base

};class derived :public base

;void test()

int main()

情形3 

帶有虛函式的類

類帶有虛函式可以分為兩種情況:

(1)類本身定義了自己的虛函式

(2)類從繼承體系中繼承了虛函式(成員函式一旦被宣告為虛函式,繼承不會改變虛函式的」虛性質「)。

這兩種情況都使乙個類成為帶有虛函式的類。這樣的類也滿足編譯器需要合成預設建構函式的類,原因是含有虛函式的類物件都含有乙個虛表指標vptr,編譯器需要對vptr設定初值以滿足虛函式機制的正確執行,編譯器會把這個設定初值的操作放在預設建構函式中。如果設計者沒有定義任何乙個預設建構函式,則編譯器會合成乙個預設建構函式完成上述操作,否則,編譯器將在每乙個建構函式中插入**來完成相同的事情。

情形4 

帶有虛基類的類

虛繼承也會在子類物件中被合成乙個指向虛基類的指標,因此也要被初始化,所以必須要建構函式,虛基類或者虛繼承保證子類物件中只有乙份虛基類的物件。

總結一下: 

不符合以上4種情形的而且沒有宣告任何建構函式的,編譯器並不會合成預設的建構函式;

並且合成的預設建構函式並不會初始化類的內建型別復合型別的資料成員。

編譯器生成預設建構函式情況

1 類和物件 當乙個a類有預設建構函式,b類中包含a類物件,並且b類沒有建構函式,那麼編譯器會給b類生成預設建構函式 2 繼承 基類有預設的建構函式,派生類沒有顯示給出建構函式。這種情況下,因為建立派生類物件會呼叫基類的建構函式,所以編譯器認為有必要生成派生類建構函式,所以會生成乙個派生類的建構函式...

C 在什麼情況下使用Using

第一種情況 using 命名空間,using指令 引用使用的外掛程式以及各種需要引用的檔案 第二種情況 using語句 用來簡化資源釋放的,在一定的範圍內有效。除了這個範圍時,自動呼叫idisposable介面的類才可以使用 例項 using sqlconnection conn new sqlco...

lib檔案什麼情況下需要重新編譯

c 中對動態鏈結庫的呼叫,一般是採用.h lib dll的方式。當然,也可以使用靜態lib或者是只有dll,然後用loadlibrary的方式呼叫 由於.lib檔案是在鏈結時使用,因此只要標頭檔案介面未發生變化,則.lib檔案不用重新編譯。對c 動態鏈結庫匯出類的情況,我們可以準備兩個.h標頭檔案。...