C++学习笔记-----存在多态调用时,为基类定义虚析构函数
在C++的繼承體系中,構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行順序是完全相反的。
對于構(gòu)造函數(shù):從繼承體系的最頂層的基類開始,一步步往下構(gòu)建。即構(gòu)造順序是 ?基類--->>派生類。
對于析構(gòu)函數(shù):從繼承體系的最底層的派生類開始,一步步向上析構(gòu)。即析構(gòu)順序是 ?派生類-->>基類。
這些對于類的實例化對象來說完全正確,但是如果在程序中存有多態(tài)指針,即基類指針指向派生類的時候,需要我們?yōu)榛愄峁┮粋€虛析構(gòu)函數(shù)。
考慮下面的例子。
讓我們一步步解釋輸出結(jié)果。
Base b;實例化一個基類的對象,調(diào)用基類的構(gòu)造函數(shù),輸出“Base Constructor”。 Derive d;實例化一個派生類的對象,會向上調(diào)用構(gòu)造函數(shù)。先調(diào)用基類的構(gòu)造函數(shù)輸出"Base Constructor“,再調(diào)用自身的構(gòu)造函數(shù)輸出"Derive Constructor"。 Base * pb = new Derive;定義了一個基類指針指向派生類,同樣會先調(diào)用基類構(gòu)造函數(shù),再調(diào)用自身構(gòu)造函數(shù)。這條語句定義了一個多態(tài)指針。 b.func();通過基類的實例化對象調(diào)用自身的virtual成員函數(shù)func,輸出”Base“d.func();通過派生類的實例化對象調(diào)用自身的virtual成員函數(shù)func, 輸出”Derive"
pb->func();通過指向派生類的基類指針調(diào)用虛函數(shù)func,因為多態(tài)指針是動態(tài)綁定的,所以此時調(diào)用的是基類的func還是派生類的func需要在運行時判斷pb指針此時此刻指向的是基類成員還是派生類成員。本例中指向派生類成員,所以會輸出"Derive"。 delete pb;釋放從堆棧申請的內(nèi)存,會先對指針所指對象進行析構(gòu),然后調(diào)用operator delete函數(shù)來釋放申請的內(nèi)存空間。
我們發(fā)現(xiàn),這條語句沒有調(diào)用派生類的析構(gòu)函數(shù),僅僅調(diào)用了基類的。這會導(dǎo)致一個問題,就是pb所指的這一個派生類對象的基類部分被析構(gòu)了,而其自身獨立于基類之外的部分沒有被析構(gòu)。就本例而言,基類的string類型變量Bmsg被析構(gòu)了,而自身的string類型變量Dmsg沒有析構(gòu)。結(jié)果會產(chǎn)生一個不完整的對象。
如前面所述,我們需要為基類提供一個虛析構(gòu)函數(shù),就像這樣
其他部分保持不變,我們來看一下輸出結(jié)果
在執(zhí)行delete pb;語句時先調(diào)用了派生類的析構(gòu)函數(shù),而后又調(diào)用了基類的析構(gòu)函數(shù)。整個對象被完全析構(gòu)了。內(nèi)存也完全被釋放了。
綜上,對于是否應(yīng)該為基類提供一個虛析構(gòu)函數(shù),我們可以這樣理解:
如果程序中存在多態(tài)指針,即存在基類指針指向派生類對象的,那么請為基類提供一個虛析構(gòu)函數(shù)。
其他的情況不需要將基類的析構(gòu)函數(shù)設(shè)置為虛函數(shù)。
總結(jié)
以上是生活随笔為你收集整理的C++学习笔记-----存在多态调用时,为基类定义虚析构函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++类成员函数在.cpp中设置成inl
- 下一篇: C++学习笔记-----继承体系中函数的