在編寫C++程序的時候,我們會為特定某一類對象申明類類型,幾乎我們申明的每一個class都會有一個或多個構造函數、一個析構函數、一個賦值運算符重載=、以及拷貝構造函數。這些函數控制著類對象的基礎操作,確保新定義的對象的初始化、完成對象撤銷時的清理工作、賦予對象新值。如果這些函數的操作出錯,則會導致嚴重的後果,所以確保這些函數的操作行為正常是非常重要的。
一、編譯器默認生成的函數
如果我們編寫一個空類,編譯器會為我們默認生成構造函數、析構函數、賦值運算符、拷貝構造函數。
例如當我們定義
class Empty{ };
就好像我們寫下了如下代碼(紅色是編譯器默認生成)
class Empty{
public:
Empty(){....} //默認構造函數
Empty(const Empty &rhs){....} //默認拷貝構造函數
~Empty(){....} //默認析構構造函數
Empty& operator=(const Empty &rhs){....} //賦值運算符
Empty* operator&(){...} //取地址運算符
const Empty* operator&() const{...} //取地址運算法的const版本
};
1. 說明:(1)這些函數只有在被調用的時候,才會被編譯器創建出來;
(2)四個函數都public且inline的;
(3)如果顯示的定義了其中某一個函數,那麼編譯器就不會生成其對應的默認的版本;
(4)自定義的拷貝構造函數不僅會覆蓋默認的拷貝構造函數,同時也會覆蓋默認的構造函數,下面的函數class構造函數,不能通過編譯
2. 實例:
下面的代碼會讓編譯器創建默認的構造函數 Empty e1; //默認構造函數
Empty e2(e1);//拷貝構造函數
e2 = e1;//賦值運算符
二、構造函數
1. 構造函數的作用
構造函數是特殊的成員函數,用來在創建對象時完成對對象屬性的一些初始化等操作, 當創建對象時, 對象會自動調用它的構造函數。
2. 默認構造函數
正如第一部分所述,如果沒有為一個類顯示定義任何構造函數、編譯器將自動為這個類生成默認構造函數。默認構造函數將依據變量初始化的規則初始化類中的所有成員:
(1)對於具有類類型的成員,會調用該成員所屬類自身的默認構造函數實現初始化;
(2)內置類型成員的初值依賴於對象如何定義,如果對象在全局作用域中定義或定義為靜態局部對象,則這些成員將被初始化為0。如果對象在局部作用域中定義,則這些成員沒有初始化;
(3)默認構造函數一般適用於僅包含類類型的成員的類;
(4)由於默認構造函數不會初始化內置類型的成員,所以必須顯示定義類的構造函數。
3. 構造函數的特點
(1)在對象被創建時自動執行;
(2)構造函數的函數名與類名相同;
(3)沒有返回值類型、也沒有返回值;
(4)構造函數不能被顯式調用;
4. 重載構造函數
可以為一個類申明的構造函數的數量沒有限制,只要每個構造函數的形參表示唯一的。定義類對象的時候,實參指定使用哪個構造函數。