1,構造:對象在創建的后所要做的一系列初始化的工作;
析構:對象在摧毀之前所要做的一系列清理工作;
2,思考:
1,子類中如何初始化父類成員?
1,對於繼承而言,子類可以獲得父類的代碼,可以獲得父類中的成員變量,成員變量從父類中傳遞到子類,那么子類對象在創建的時候如何初始化從父類中繼承的成員變量呢?
2,父類構造函數和子類構造函數有有什么關系?
3,子類對象的構造:
1,子類中可以定義構造函數;
1,子類中定義的新的構造函數,對於子類對象創建的時候必須完成一系列的初始化工作,這些初始化工作包括初始化繼承而來的成員,第一種方式直接對他們進行賦值或者直接將他們寫到初始化列表中去進行初始化,第二種方式更直接,在子類構造的時候我們調用父類構造函數進行初始化;
2,這就是子類構造函數可以用來初始化父類成員的兩種方式;
2,子類構造函數:
1,必須對繼承而來的成員進行初始化;
1,直接通過初始化列表或者賦值的方式進行初始化;
1,有可能從父類中繼承了 private 成員,因此直接來進行賦值或初始化根本就是行不通的,因此這個時候只能通過父類的構造函數來進行初始化的工作;
2,調用父類構造函數進行初始化;
3,父類構造函數在子類中的調用方式;
1,默認調用:
1,子類對象在創建的時候會自動的調用父類的構造函數;
2,適用於無參構造函數和使用默認參數的構造函數;
1,對於需要參數的構造函數來說,默認的調用方式是行不通的,必須顯示調用;
2,顯示調用:
1,通過初始化列表進行調用;
1,只能在初始化列表中調用;
2,適用於所有父類構造函數;
3,父類構造函數的調用:
1,代碼示例:
1 class Child : public Parent 2 { 3 Public: 4 Child() /* 隱式調用 */ 5 { 6 Cout << “Child()” << endl; 7 } 8 9 Child(string s) : Parent(“Parameter to Parent”) /* 顯示調用 */ 10 { 11 Cout << “Child() : “ << s << endl; 12 } 13 };
4,子類的構造初探編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 Parent() 10 { 11 cout << "Parent()" << endl; 12 } 13 14 Parent(string s) 15 { 16 cout << "Parent(string s) : " << s << endl; 17 } 18 }; 19 20 class Child : public Parent 21 { 22 public: 23 Child() // 隱式調用父類構造函數中的無參或默認初始值構造函數 24 { 25 cout << "Child()" << endl; 26 } 27 28 Child(string s) // 隱式調用父類構造函數中的無參或默認初始值構造函數; 29 { 30 cout << "Child(string s) : " << s << endl; 31 } 32 33 Child(string s): Parent(s) // 顯示調用父類構造函數; 34 { 35 cout << "Child(string s) : " << s << endl; 36 } 37 }; 38 39 int main() 40 { 41 Child c; // 調用父類無參構造函數,然后調用子類無參構造函數; 42 Child cc("cc"); // 調用父類有參構造函數,然后調用子類構造函數; 43 44 return 0; 45 }
1,子類和父類的構造函數的調用都嚴格按照重載規則調用;
5,子類對象的構造:
1,構造規則:
1,子類對象在創建時會首先調用父類的構造函數(要以子類構造函數調用為依據);
2,先執行父類構造函數再執行子類構造函數;
3,父類構造函數可以被隱式調用或者顯示調用;
2,對象創建時構造函數的調用順序:
1,調用父類的構造函數;
2,調用成員變量的構造函數;
3,調用類自身的構造函數;
4,口訣:
1,先父母(調到最上的父母為止),后客人(按照成員變量申明的順序),再自己;
2,非常實用;
3,子類構造深度解析編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Object 7 { 8 public: 9 Object(string s) 10 { 11 cout << "Object(string s) : " << s << endl; 12 } 13 }; 14 15 class Parent : public Object 16 { 17 public: 18 Parent() : Object("Default") // 必須顯示調用 19 { 20 cout << "Parent()" << endl; 21 } 22 23 Parent(string s) : Object(s) // 必須顯示調用 24 { 25 cout << "Parent(string s) : " << s << endl; 26 } 27 }; 28 29 class Child : public Parent 30 { 31 Object mO1; // 組合關系,默認構造函數和有參數構造函數,這里必須顯示調用 32 Object mO2; 33 34 public: 35 Child() : mO1("Default 1"), mO2("Default 2") 36 { 37 cout << "Child()" << endl; 38 } 39 40 Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2") // 父母和成員客人的區別在於父母構造函數直接調用,客人構造函數通過對象調用; 41 { 42 cout << "Child(string s) : " << s << endl; 43 } 44 }; 45 46 int main() 47 { 48 Child cc("cc"); 49 50 // cc output: 51 // Object(string s) : cc 父母 52 // Parent(string s) : cc 父母 53 // Object(string s) : cc 1 客人 54 // Object(string s) : cc 2 客人 55 // Child(string s) : cc 自己 56 57 return 0; 58 }
6,子類對象的析構:
1,析構函數的調用順序與構造函數相反:
1,執行自身的析構函數;
2,執行成員變量的析構函數;
3,執行父類的析構函數;
2,對象的析構編程實驗:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Object 7 { 8 string ms; // 為了驗證析構函數的輸出,定義了這個成員變量來傳遞值,因為構造函數可以由外界傳入值,但是析構函數沒有參數,是不可以由完結傳入值的; 9 10 public: 11 Object(string s) 12 { 13 cout << "Object(string s) : " << s << endl; 14 ms = s; 15 } 16 17 ~Object() 18 { 19 cout << "~Object() : " << ms << endl; 20 } 21 }; 22 23 class Parent : public Object 24 { 25 string ms; 26 27 public: 28 Parent() : Object("Default") 29 { 30 cout << "Parent()" << endl; 31 ms = "Default"; 32 } 33 34 Parent(string s) : Object(s) 35 { 36 cout << "Parent(string s) : " << s << endl; 37 ms = s; 38 } 39 40 ~Parent() 41 { 42 cout << "~Parent() : " << ms << endl; 43 } 44 }; 45 46 class Child : public Parent 47 { 48 Object mO1; 49 Object mO2; 50 string ms; 51 52 public: 53 Child() : mO1("Default 1"), mO2("Default 2") 54 { 55 cout << "Child()" << endl; 56 ms = "Default"; 57 } 58 59 Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2") 60 { 61 cout << "Child(string s) : " << s << endl; 62 ms = s; 63 } 64 65 ~Child() 66 { 67 cout << "~Child() " << ms << endl; 68 } 69 }; 70 71 int main() 72 { 73 Child cc("cc"); 74 75 cout << endl; 76 77 return 0; 78 }
7,小結:
1,子類對象在創建時需要調用父類構造函數進行初始化;
2,先執行父類構造函數然后執行成員的析構函數;
3,父類構造函數顯示調用需要在初始化列表中進行;
4,子類對象在銷毀時需要調用父類析構函數進行清理;
5,析構順序與構造順序對稱相反;
1,先自己,后客人,再父母;