您好,登錄后才能下訂單哦!
這篇文章主要講解了“c++繼承中的構造與析構方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“c++繼承中的構造與析構方法是什么”吧!
我們思考下這個問題:如何初始化父類成員?父類構造函數和子類構造函數有何關系呢?在子類中可以定義構造函數,子類構造函數必須對繼承而來的成員進行初始化:a> 直接通過初始化列表或者賦值的方式進行初始化;b> 調用父類構造函數進行初始化。
下來我們來說說父類構造函數在子類中的調用方式,分為兩種:a> 默認調用:適用于無參構造函數和使用默認參數的構造函數;b> 顯示調用:通過初始化列表進行調用,適用于所有父類構造函數。那么隱式調用是在子類的構造函數中啥都不加,顯示調用時在子類構造函數后加上父類構造函數,如下所示
下來我們就對子類的構造函數一探究竟
#include <iostream> #include <string> using namespace std; class Parent { public: Parent(string s) { cout << "Parent(string s): " << s << endl; } }; class Child : public Parent { public: Child() { cout << "Child()" << endl; } Child(string s) : Parent(s) { cout << "Child(string s): " << s << endl; } }; int main() { Child c; Child cc("cc"); return 0; }
我們先來分析下,在子類 Child 中,它定義的第一個構造函數顯然是隱式調用父類的構造函數。但是在父類的構造函數中,我們既沒有定義無參構造函數,也沒有定義默認參數的構造函數,所以這個隱式調用肯定會出錯。而第二個對象 cc 是進行顯示調用的,所以它不會報錯。我們來看看編譯結果
它報錯說第 19 行出錯,也就是子類的隱調用出錯了,下來我們在父類中通過一個無參構造函數,來看看編譯是否還會出錯呢
我們看到編譯通過了,并且也完美運行。我們來說說子類對象的構造規則:a> 子類對象在創建時會首先調用父類的構造函數;b> 先執行父類的構造函數再執行子類的構造函數;c> 父類構造函數可以被隱式調用或者顯示調用。那么子類對象的創建時構造函數的調用又有什么順序呢?1、調用父類的構造函數;2、調用成員變量的構造函數;3、調用類自身的構造函數。對此,有唐長老總結的一個口訣心法:先父母,后客人,再自己。
下來我們通過編程來看看子類創建時構造函數的執行順序
#include <iostream> #include <string> using namespace std; class Object { string ms; public: Object(string s) { ms = s; cout << "Object(string s): " << ms << endl; } }; class Parent : public Object { string ms; public: Parent() : Object("Default") { ms = "Default"; cout << "Parent()" << endl; } Parent(string s) : Object(s) { ms = s; cout << "Parent(string s): " << s << endl; } }; class Child : public Parent { Object mOb1; Object mOb2; string ms; public: Child() : mOb1("Default 1"), mOb2("Default 2") { ms = "Default"; cout << "Child()" << endl; } Child(string s) : Parent(s), mOb1(s + " 1"), mOb2(s + " 2") { ms = s; cout << "Child(string s): " << s << endl; } }; int main() { Child c; // c output: // Object(string s): Default // Parent() // Object(string s): Default 1 // Object(string s): Default 2 // Child() cout << endl; Child cc("cc"); // cc output: // Object(string s): Default // Parent(string s) : cc // Object(string s): cc 1 // Object(string s): cc 2 // Child(string s): cc return 0; }
我們來分析下,類Child c 創建時首先會隱式調用它的父類構造函數 Parent() : Object("Default"),而 Parent 創建時會先調用它的父類 Object 的構造函數 Object("Default")。再來調用成員對象 mOb1 和 mOb2 的構造函數 mOb1("Default 1"), mOb2("Default 2"),最后調用自己的構造函數 Child()。所以最后打印的應該和我們程序中寫的是一致的。再來看看對象 cc 的創建過程,因為它是顯示調用,所以會調用構造函數 Parent(s) ,而 Parent 的父類 Object 也會調用構造函數 Object(string s) 。額庵后調用成員對象 mOb1 和 mOb2 的構造函數 mOb1(s + "1"), mOb2(s + "2"),最后調用自己的構造函數 Child(string s)。打印的應該也和我們在程序中寫的一致。我們來看編譯結果
結果和我們分析的是一致的。那么再來看看析構函數的調用順序,它跟構造函數的順序剛好相反:1、執行自身的析構函數;2、執行成員變量的析構函數;3、執行父類的析構函數。依舊是在上面的程序基礎之上,來看看析構函數的執行順序。
#include <iostream> #include <string> using namespace std; class Object { string ms; public: Object(string s) { ms = s; cout << "Object(string s): " << ms << endl; } ~Object() { cout << "~Object() : " << ms << endl; } }; class Parent : public Object { string ms; public: Parent() : Object("Default") { ms = "Default"; cout << "Parent()" << endl; } Parent(string s) : Object(s) { ms = s; cout << "Parent(string s): " << s << endl; } ~Parent() { cout << "~Parent() : " << ms << endl; } }; class Child : public Parent { Object mOb1; Object mOb2; string ms; public: Child() : mOb1("Default 1"), mOb2("Default 2") { ms = "Default"; cout << "Child()" << endl; } Child(string s) : Parent(s), mOb1(s + " 1"), mOb2(s + " 2") { ms = s; cout << "Child(string s): " << s << endl; } ~Child() { cout << "~Child() : " << ms << endl; } }; int main() { Child cc("cc"); return 0; }
我們來看看編譯結果
感謝各位的閱讀,以上就是“c++繼承中的構造與析構方法是什么”的內容了,經過本文的學習后,相信大家對c++繼承中的構造與析構方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。