前言
經過前兩篇隨筆( 上 中 )的分析我們已經解決了具有指標成員的同類物件“ 干涉 ”問題。可惜,前面給出的解決方案程式碼還是不完整。還有什麼問題呢?觀察發現,建構函式裡面有new的關鍵字出現,也就是說開闢了新的記憶體空間,我們也知道new必須也只能對應一個delete,而不應該讓系統自己處理( 還不熟練new和delete用法的點這裡 ),但這裡和new對應的delete去哪裡了?
解決思路
應該何時delete?顯然,應該在物件銷燬的時候delete。C++中定義了這樣一種函式 --- 解構函式,它與建構函式相對應,能在物件被銷燬時自動執行。
對【複製控制( 中 )解決方案】的改進
下面的程式碼對【複製控制( 中 )解決方案】進行了進一步的改進 --- 設定了自定義的解構函式。至此,複製控制已經完全實現,我們可以正確效率地實現物件( 不論有無指標成員 )間的複製功能了:
1 #include <iostream> 2 #include <cstdlib> 3 #include <fstream> 4 #include <string> 5 6 using namespace std; 7 8 class A { 9 public: 10 // 建構函式為指標成員開闢空間並賦初值0 11 A() { 12 num_p = new int; 13 *num_p = 0; 14 } 15 // 自定義複製函式 16 A(const A & a) { 17 num_p = new int; 18 *num_p = a.getNum(); 19 } 20 // 自定義賦值運算子號 21 A & operator=(const A & a) { 22 num_p = new int; 23 *num_p = a.getNum(); 24 } 25 // 自定義解構函式 26 ~A() { 27 delete num_p; 28 cout << "物件正常銷燬" << endl; 29 } 30 // 給指標所指物件賦值 31 void setNum(int num) { 32 *num_p = num; 33 } 34 // 獲取指標所指物件 35 int getNum() const { 36 int num = *num_p; 37 return num; 38 } 39 private: 40 int *num_p; 41 }; 42 43 int main() 44 { 45 A a1, a3; 46 47 // 設定a1指標成員所指物件的值 48 a1.setNum(1); 49 // 呼叫自定義的複製函式 50 A a2=a1; 51 // 啟用自定義的賦值運算子 52 a3 = a1; 53 // 觀察得出a1,a2, a3的指標成員所指物件均為整數1。 54 cout << "a1`s num: " << a1.getNum() << endl; 55 cout << "a2`s num: " << a2.getNum() << endl; 56 cout << "a3`s num: " << a3.getNum() << endl; 57 58 // 修改a1指標成員所指物件的值 59 a1.setNum(2); 60 // 觀察得出a1的指標成員所指物件改了,a2, a3的沒變。 61 cout << "a1`s num: " << a1.getNum() << endl; 62 cout << "a2`s num: " << a2.getNum() << endl; 63 cout << "a3`s num: " << a3.getNum() << endl; 64 65 return 0; 66 }
執行結果:
觀察發現每個物件都使用了自定義的解構函式。
說明
一個有用的經驗法則:如果類需要解構函式,它同時也需要自定義複製函式,過載賦值運算子。( 這就是C++中著名的“ 三法則 ” )