眾所周知,幾乎所有的面向對象的編程語言都保護構造函數與析構函數,好學者就要舉手了,啥情況啊,Java裡面不就沒有析構函數嘛。好吧,你問倒我了,不過可以認為Java的垃圾自動回收機制實現了對象析構的功能。管他呢,還是看C++的構造函數和析構函數吧。
構造函數
對於C++的構造函數,暫且將其分為以下幾類:
1. 默認構造函數
2. 隱士轉換構造函數
3. 拷貝構造函數
4. 其它構造函數
1. 默認構造函數表示沒有任何參數的構造函數,當自定義任何構造函數以後,將不再自動創建默認構造函數,當然,默認構造函數啥也不干,程序員關心系數頓時大跌。關於默認構造函數還需要關心的一個問題是,當本類繼承於另一個類(即父類),父類沒有默認構造函數時,本類將自動沒有構造函數,並且還必須定義至少能夠支持父類初始化的構造函數。
2. 隱士轉換構造函數時什麼呢?它是這樣一類構造函數,這類構造函數僅含有一個參數。由於C++規定,為只含有一個參數的構造函數自動定義一種隱士轉換,將構造函數的參數對應數據類型的對象轉換為類對象。如下面例子所示:
其中字符串“hello friends”通過隱士轉換構造函數轉換為了String類對象s。這裡不得不提一個關鍵字explicit,比較悲劇的是學了好幾年C++後才知道這麼一個關鍵字,這也充分體現了一本好書的重要性。下面來看看explicit的用法,再解釋。
explicit僅用於構造函數,且僅用於隱士轉換構造函數,其目的是禁止隱士構造函數功能。如上代碼所示,當為構造函數添加explicit關鍵字後,String s = "hello friends"; 編譯不通過。當然,此時構造函數本身還是能夠正常工作的。
3. 拷貝構造函數,就是用來復制對象的一種特殊的構造函數。通過它,可以使用一個已經創建好的對象(由拷貝構造函數的參數指定)去初始化一個正准備創建的同類對象。
如上述代碼所述,拷貝構造函數只能有一個參數,並且必須是同類對象的引用。每個類都應該有一個拷貝構造函數,如果用戶沒有指定,將使用默認的拷貝構造函數。默認拷貝構造函數執行對象的全部內容復制,但有時需要有選擇、有變化地復制。這種情況就需要顯示定義拷貝構造函數,並實現為感興趣部分的復制或者為新對象添加某些屬性值。
拷貝構造函數最常見的使用方式是在類中含有指針類型屬性時,因為默認的拷貝函數是按指拷貝的,即所謂的淺拷貝。這時需要顯示定義拷貝構造函數,並顯示地將指針從新分配內存並copy以前指向的值到新分配的內存中。
4. 其它構造函數,沒什麼特別的,就是前面1,2,3未包含的構造函數均屬於該類。