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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈构造函数与构析函数的调用顺序(转载)

發布時間:2024/4/17 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈构造函数与构析函数的调用顺序(转载) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

構造函數?

??? 先看看構造函數的調用順序規則,只要我們在平時編程的時候遵守這種約定,任何關于構造函數的調用問題都能解決;構造函數的調用順序總是如下:
1.基類構造函數。如果有多個基類,則構造函數的調用順序是某類在類派生表中出現的順序,而不是它們在成員初始化表中的順序。
2.成員類對象構造函數。如果有多個成員類對象則構造函數的調用順序是對象在類中被聲明的順序,而不是它們出現在成員初始化表中的順序。
3.派生類構造函數。

?

析構函數

? ???析構函數的調用順序與構造函數的調用順序正好相反,將上面3個點反過來用就可以了,首先調用派生類的析構函數;其次再調用成員類對象的析構函數;最后調用基類的析構函數。
????析構函數在下邊3種情況時被調用:
????1.對象生命周期結束,被銷毀時(一般類成員的指針變量與引用都i不自動調用析構函數);
????2.delete指向對象的指針時,或delete指向對象的基類類型指針,而其基類虛構函數是虛函數時;
????3.對象i是對象o的成員,o的析構函數被調用時,對象i的析構函數也被調用。

下面用例子來說說構造函數的的調用順序:
#include "stdafx.h" #include "iostream" using namespace std; class Base { public:Base(){ std::cout<<"Base::Base()"<<std::endl; }~Base(){ std::cout<<"Base::~Base()"<<std::endl; } };class Base1:public Base { public:Base1(){ std::cout<<"Base1::Base1()"<<std::endl; }~Base1(){ std::cout<<"Base1::~Base1()"<<std::endl; } };class Derive { public:Derive(){ std::cout<<"Derive::Derive()"<<std::endl; }~Derive(){ std::cout<<"Derive::~Derive()"<<std::endl; } };class Derive1:public Base1 { private:Derive m_derive; public:Derive1(){ std::cout<<"Derive1::Derive1()"<<std::endl; }~Derive1(){ std::cout<<"Derive1::~Derive1()"<<std::endl; } };int _tmain(int argc, _TCHAR* argv[]) {Derive1 derive;return 0; }

?

運行結果是:
Base::Base() Base1::Base1() Derive::Derive() Derive1::Derive1() Derive1::~Derive1() Derive::~Derive() Base1::~Base1() Base::~Base()

?

那么根據上面的輸出結果,筆者稍微進行一下講解,構造函數的調用順序是;首先,如果存在基類,那么先調用基類的構造函數,如果基類的構造函數中仍然存在基類,那么程序會繼續進行向上查找,直到找到它最早的基類進行初始化;如上例中類Derive1,繼承于類Base與Base1;其次,如果所調用的類中定義的時候存在著對象被聲明,那么在基類的構造函數調用完成以后,再調用對象的構造函數,如上例中在類Derive1中聲明的對象Derive m_derive;最后,將調用派生類的構造函數,如上例最后調用的是Derive1類的構造函數。

virtual析構函數

?

下面來說一說為多態基類聲明virtual析構函數:
在C++中,構造函數不能聲時為虛函數,這是因為編譯器在構造對象時,必須知道確切類型,才能正確的生成對象,因此,不允許使用動態束定;其次,在構造函數執行之前,對象并不存在,無法使用指向此此對象的指針來調用構造函數,然而,析構函數是可以聲明為虛函數;C++明白指出,當derived class對象經由一個base class指針被刪除,而該base class帶著一個non-virtual析構函數,其結果未有定義---實際執行時通常發生的是對象的derived成分沒被銷毀掉。

看下面的例子:
class Base { public:Base(){ std::cout<<"Base::Base()"<<std::endl; }~Base(){ std::cout<<"Base::~Base()"<<std::endl; } };class Derive:public Base { public:Derive(){ std::cout<<"Derive::Derive()"<<std::endl; }~Derive(){ std::cout<<"Derive::~Derive()"<<std::endl; } };int _tmain(int argc, _TCHAR* argv[]) {Base* pBase = new Derive(); //這種base classed的設計目的是為了用來"通過base class接口處理derived class對象"delete pBase;return 0; }

?

輸出的結果是:
Base::Base() Derive::Derive() Base::~Base()

?

從上面的輸出結果可以看出,析構函數的調用結果是存在問題的,也就是說析構函數只作了局部銷毀工作,這可能形成資源泄漏敗壞數據結構等問題;那么解決此問題的方法很簡單,給base class一個virtual析構函數;

class Base { public:Base(){ std::cout<<"Base::Base()"<<std::endl; }virtual ~Base(){ std::cout<<"Base::~Base()"<<std::endl; } };class Derive:public Base { public:Derive(){ std::cout<<"Derive::Derive()"<<std::endl; }~Derive(){ std::cout<<"Derive::~Derive()"<<std::endl; } };int _tmain(int argc, _TCHAR* argv[]) {Base* pBase = new Derive();delete pBase;return 0; }

?

輸出結果是:
Base::Base() Derive::Derive() Derive::~Derive() Base::~Base()

?

可能上面的輸出結果正是我們所希望的吧!由此還可以看出虛函數還是多態的基礎,在C++中沒有虛函數就無法實現多態特性;因為不聲明為虛函數就不能實現“動態聯編”,所以也就不能實現多態啦!

?

?

轉載地址:http://blog.csdn.net/bresponse/article/details/6914155

轉載于:https://www.cnblogs.com/alice123/articles/5704434.html

總結

以上是生活随笔為你收集整理的浅谈构造函数与构析函数的调用顺序(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。

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