C 空類中的預設函式

2021-06-21 09:45:23 字數 1606 閱讀 3175

參加面試的時候,面試官問到這個問題,我的回答:預設建構函式、預設析構函式、預設拷貝建構函式、預設賦值函式。現在回想起來感覺不對,就google,揭示一下這個看似簡單的問題:

乙個空的class在c++編譯器處理過後就不再為空,編譯器會自動地為我們宣告一些member function,如果你寫 

class a{};

編譯器處理後,就相當於: 

class a

;  基本上符合我上文的回答,只是多了取位址運算子的兩個函式。

這種回答對否?

其實對於這樣的乙個空類來說,是完全沒有必要的,而編譯器也不是這樣做的。編譯器的做法是:

只有你需要用到這些函式並且你又沒有顯示的宣告這些函式的時候,編譯器才會貼心的自動宣告相應的函式。  

比如   

a   a;   

編譯器就會根據上面的例項,給類a生成建構函式和析構函式。   

當使用   

a   b(b);   

編譯器就會生成類a的拷貝建構函式。   

a   c;   

c   =   a;   

編譯器生成賦值運算子函式   

a   &d   =   a;   

編譯器生成取位址運算子函式。   

經過我們的分析可以這樣理解:對於乙個沒有例項化的空類,編譯器是不會給它生成任何函式的,當例項化乙個空類後,編譯器會根據需要生成相應的函式。這條理論同樣適合非空類(只宣告變數,而不宣告函式)。

題外話,方便記住:

其中的預設拷貝賦值操作符只有在生成的**合法並且有機會證明它有意義存在時才會生成。這就說明,如果你打算在乙個「內含引用成員」或者「內含const成員」的類內支援賦值操作,就必須定義自己的預設拷貝賦值操作符。因為c++本身不允許引用改指不同的物件,也不允許更改const成員。

最後一種情況,當基類將自己的預設拷貝賦值操作符宣告為private時,子類就不會產生自己的的預設拷貝賦值操作符。因為假如產生了這樣的預設拷貝賦值操作符,它會試著去呼叫基類的預設拷貝賦值操作符去處理基類的部分,不幸的是,它沒有權利。

你可以將拷貝建構函式或缺省拷貝賦值操作符宣告為private。這樣明確宣告乙個成員函式,就阻止了編譯器暗自建立的預設版本,而這些函式為private,使得可以成功阻止人們呼叫它。

上面的做法有乙個隱患,因為類自身的member和friend還是可以呼叫這些private函式。有乙個很刁鑽的方法,「將成員函式宣告為private而且故意不實現它們」,這樣既阻止了預設函式的生成,而且如果你試著呼叫這些函式,就會得到乙個鏈結錯誤。只宣告,不定義,鏈結器報錯。甚至在宣告的時候,你連引數也不用寫。

只要類裡有指標變數就得自己寫拷貝建構函式和賦值函式,但是你確定用不著這些函式時,可以把這些函式做private宣告而不去實現它,這就防止了會有人去呼叫它們,也防止了編譯器去生成它們。

如果沒有自定義複製建構函式,則系統會建立預設的複製建構函式,但系統建立的預設複製建構函式只會執行「淺拷貝」,即將被拷貝物件的資料成員的值一一賦值給新建立的物件,若該類的資料成員中有指標成員,則會使得新的物件的指標所指向的位址與被拷貝物件的指標所指向的位址相同,delete該指標時則會導致兩次重複delete而出錯。

C 中的空類預設產生的類成員函式

對於乙個c 的空類 比如empty 1 class empty 2 雖然empty類定義中沒有任何成員,但為了進行一些預設的操作,編譯器會加入以下一些成員函式,這些成員函式使得類的物件擁有一些通用的功能 1 預設建構函式和複製建構函式。他們被用於類的物件的構造過程。2 析構函式。它被用於類的物件的析...

C 中類的預設建構函式

在 c 中類的合成的預設建構函式2 1 和 c 中類的合成的預設建構函式2 2 中提到,如果類中沒有顯式地定義預設建構函式,則c 編譯器會為其創造乙個合成的預設建構函式,如果類中已經定義了其他格式的建構函式,此時c 編譯器不會再為其合成預設建構函式。而定義類時,最好要定義其預設的建構函式。在c 11...

C 類的預設函式

使用者自定義乙個類,簡單的可以看成是乙個新的型別,與c 標準裡面的資料型別使用差不多。但在物件導向程式設計中,我們知道任何乙個物件必須要通過建構函式才能建立,以及可以將乙個物件拷貝給另乙個物件,將乙個物件作為引數傳遞給乙個函式等。c 預設函式 既然是預設函式,那也就是說即便類裡面乙個成員函式沒有,這...