日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

构造函数和析构函数的调用过程

發布時間:2025/10/17 8 豆豆
生活随笔 收集整理的這篇文章主要介紹了 构造函数和析构函数的调用过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
下面代碼的輸出是什么?(D) class A { public: A() { } ~A() { cout<<"~A"<<endl; } }; class B:public A { public: B(A &a):_a(a) { } ~B() { cout<<"~B"<<endl; } private: A _a; }; int main(void) { A a; //很簡單,定義a的時候調用了一次構造函數 B b(a); }A、~B
B、~B ~A
C、~B ~A ~A

D、~B ~A ~A ~A



been:
B(A &a):_a(a)
這個引用也是值得注意的,這里提醒大家一下,去掉引用,第一個析構是是~A


靈靈:
下面以例子說明參數為類對象,是否有初始化列表時構造與析構函數的執行順序:

#include <iostream> using namespace std;class A { public: A(){ cout<<"A"<<endl; }A(const A& other){ cout<<"copy A"<<endl;}~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A a):_a(a) // B(A &a):_a(a) 會有完全不同的結果{cout<<"B"<<endl;}~B() { cout<<"~B"<<endl; } private: A _a; };void main(void) {A a;B b(a);return;}運行結果:A //A a 創建對象a執行A類的構造copy A //B b(a) 傳參的時候利用A類的復制構造A //創建對象B調用基類A的構造copy A //使用初始化列表初始化成員_a利用A類的復制構造B //調用自己的構造~A //析構參數~B //析構自身~A //析構B類成員~A //再析構基類的~A //析構 對象aclass A { public: A(){ cout<<"A"<<endl; }A(const A& other){ cout<<"copy A"<<endl;}~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A a) //若此處換為:B(A &a),則不調用構造函數{cout<<"B"<<endl;}~B() { cout<<"~B"<<endl; } private: A _a; };void main(void) {A a; B b(a);return;} 運行結果:A <span style="font-family: Arial, Helvetica, sans-serif;">//A a 創建對象a執行A類的構造</span>copy A //B b(a) 傳參的時候利用A類的復制構造A //創建對象B調用基類A的構造A //初始化B類的成員執行A類的構造B //調用自己的構造~A //析構參數~B //析構自身~A //析構B類成員~A //再析構基類的~A //析構 對象a


vzhuzhu:
對于構造函數:基類構造函數 > 子類成員變量構造函數 > 子類構造函數
對于析構函數:子類析構函數 > 子類成員變量析構函數 > 基類析構函數
可以看出構造函數的調用過程和析構函數的調用過程正好相反。



水澤淵:
在vs上運行之后發現,輸出順序確實如@Aesthetic92所說,然而@賴聰林說的也沒有錯,可是@賴聰林舉的例子并沒有用到拷貝構造函數。
原題-----------------------------------------------------------------------------

class A { public: A() { cout<<"A"<<endl; } ~A() { cout<<"~A"<<endl; } }; class B:public A { public: B(A &a):_a(a) { cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; }private: A _a; }; void main(void) { A a; B b(a); } // 結果為 A A B ~B ~A ~A ~A
加上拷貝構造函數---------------------------------------------------------------------- <pre name="code" class="cpp"> class A { public: A(){ cout<<"A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} ~A() { cout<<"~A"<<endl; } }; class B:public A {public:B(A &a):_a(a) {cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; } private: A _a; }; void main(void) {A a; B b(a);} //結果顯示 A A copy A B ~B ~A ~A ~A
修改后---------------------------------------------------------------------------------- class A {public: A() { cout<<"A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} ~A() { cout<<"~A"<<endl; } };class B:public A {public:B(A &a) { cout<<"B"<<endl; } ~B() { cout<<"~B"<<endl; }private: A _a; };voidmain(void){ A a; B b(a);} //結果為 A A A B ~B ~A ~A ~A


Aesthetic92:
答案:選D
答案解析:答案看起來可能比較怪,其實給默認構造函數補上輸出,然后再在基類里寫個復制構造函數,這樣結果就很明朗了;
首先 A a;這個調用A的默認構造函數,
B b(a); 因為A &a,形參為引用,不需要調用基類復制構造函數(其實基類也沒寫);_a(a)首先創建對象_a,調用基類A的默認構造函數,然后調用基類復制構造函數(測試的時候可以寫出來),把a對象賦給_a,結束之后調用B的析構函數,輸出~B;然后調用基類A的析構函數撤銷復制構造函數,輸出~A;調用基類A的析構函數撤銷_a,輸出~A;最后調用基類A的析構函數撤銷一開始創建的A a,輸出~A



kuring:
要想搞明白該問題,需要理解基類構造析構函數、子類構造析構函數和子類成員變量構造析構函數的調用順序。
對于構造函數:基類構造函數 > 子類成員變量構造函數 > 子類構造函數
對于析構函數:子類析構函數 > 子類成員變量析構函數 > 基類析構函數
可以看出構造函數的調用過程和析構函數的調用過程正好相反。

main函數中首先構造變量a,然后是b。在構造b時首先調用b的基類A的構造函數,然后調用b中成員變量_a的構造函數,最后調用b的構造函數。
main函數調用結束返回時,變量的釋放順序跟變量的構造順序正好相反。首先釋放變量b,然后是變量a。
在釋放變量b時,首先調用b的析構函數,然后析構變量b的成員_a,析構_a時調用_a的析構函數。再調用b的基類的析構函數。
然后是釋放變量a,調用a的析構函數。

本例子中應該將A的析構函數更改為virtual的,防止使用多態機制時出現子類對象無法釋放的情況,本例子中沒有用到多態機制,不存在該問題。



賴聰林:

# include <iostream> using namespace std; class A { public: A() { cout<<"create A"<<endl; } A(const A& other){ cout<<"copy A"<<endl;} //復制構造函數~A() { cout<<"~A"<<endl; } }; class C { public:C() { cout<<"create C"<<endl; } C(const A& other){ cout<<"copy C"<<endl;} //復制構造函數~C() { cout<<"~C"<<endl; } }; class B:public A { public: B(){ cout<<"create B"<<endl;} ~B() { cout<<"~B"<<endl; } private: C _a; }; int main(void) {B b; cout<<"------------------------"<<endl; }//上面的輸出結果為 create A create C create B ------------------------ ~B ~C ~A
我們可以看到,這個地方先是調用parent class的構造函數,然后對成員變量C類型的構造函數,然后再最后執行B類型的構造函數。
析構的過程就是上面的過程反過來。

所以Aesthetic92的解釋有一部分不是很準確。我認為。

更加準確的說明應該是,
最開始析構b,~B,這個是沒有爭議的。
接著是析構b的成員變量_a,所以是~A
接著是b的parent class(基類)的~A
最后才是a的析構~A
不過為了理解這道題,我感覺配上我的例子更好理解一點,原題的成員變量和基類都是相同的類型,比較難以辨認。

總結

以上是生活随笔為你收集整理的构造函数和析构函数的调用过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。