詳解C++中虛析構函數(shù)的作用及其原理分析
C++中的虛析構函數(shù)到底什么時候有用的,什么作用呢。
一.虛析構函數(shù)的作用
總的來說虛析構函數(shù)是為了避免內存泄露,而且是當子類中會有指針成員變量時才會使用得到的。也就說虛析構函數(shù)使得在刪除指向子類對象的基類指針時可以調用子類的析構函數(shù)達到釋放子類中堆內存的目的,而防止內存泄露的.
我們知道,用C++開發(fā)的時候,用來做基類的類的析構函數(shù)一般都是虛函數(shù)??墒?,為什么要這樣做呢?下面用一個小例子來說明:
#include<iostream>
using namespace std;
class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() { cout<<"delete ClxBase"<<endl; };
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(int argc, char const* argv[])
{
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
return 0;
}

但是,如果把類ClxBase析構函數(shù)前的virtual去掉,那輸出結果就是下面的樣子了:

沒有調動子類的析構函數(shù)
也就是說,類ClxDerived的析構函數(shù)根本沒有被調用!一般情況下類的析構函數(shù)里面都是釋放內存資源,而析構函數(shù)不被調用的話就會造成內存泄漏。我想所有的C++程序員都知道這樣的危險性。當然,如果在析構函數(shù)中做了其他工作的話,那你的所有努力也都是白費力氣。
所以,文章開頭的那個問題的答案就是--這樣做是為了當用一個基類的指針刪除一個派生類的對象時,派生類的析構函數(shù)會被調用。
當然,并不是要把所有類的析構函數(shù)都寫成虛函數(shù)。因為當類里面有虛函數(shù)的時候,編譯器會給類添加一個虛函數(shù)表,里面來存放虛函數(shù)指針,這樣就會增加類的存儲空間。所以,只有當一個類被用來作為基類的時候,才把析構函數(shù)寫成虛函數(shù)。
總結一下虛析構函數(shù)的作用:
(1)如果父類的析構函數(shù)不加virtual關鍵字
當父類的析構函數(shù)不聲明成虛析構函數(shù)的時候,當子類繼承父類,父類的指針指向子類時,delete掉父類的指針,只調動父類的析構函數(shù),而不調動子類的析構函數(shù)。
(2)如果父類的析構函數(shù)加virtual關鍵字
當父類的析構函數(shù)聲明成虛析構函數(shù)的時候,當子類繼承父類,父類的指針指向子類時,delete掉父類的指針,先調動子類的析構函數(shù),再調動父類的析構函數(shù)。
二.虛析構函數(shù)的原理分析
#include<iostream>
using namespace std;
class Base
{
public:
Base(){cout<<"create Base"<<endl;}
virtual ~Base(){cout<<"delete Base"<<endl;}
};
class Der : public Base
{
public:
Der(){cout<<"create Der"<<endl;}
~Der(){cout<<"Delete Der"<<endl;}
};
int main(int argc, char const* argv[])
{
Base *b = new Der;
delete b;
return 0;
}
從創(chuàng)建講起,用gdb調試你會發(fā)現(xiàn),
(1)先調用父類的構造函數(shù),再調用子類的構造函數(shù),
這里有一個問題:父類的構造函數(shù)/析構函數(shù)與子類的構造函數(shù)/析構函數(shù)會形成多態(tài),但是當父類的構造函數(shù)/析構函數(shù)即使被聲明virtual,子類的構造/析構方法仍無法覆蓋父類的構造方法和析構方法。這是由于父類的構造函數(shù)和析構函數(shù)是子類無法繼承的,也就是說每一個類都有自己獨有的構造函數(shù)和析構函數(shù)。
(2)而由于父類的析構函數(shù)為虛函數(shù),所以子類會在所有屬性的前面形成虛表,而虛表內部存儲的就是父類的虛函數(shù)
即使子類也有虛函數(shù),但是由于是單繼承,所以也只有一張?zhí)摫?,這在上一篇博客多態(tài)中講到過。
執(zhí)行 Base *b = new Der;之后b的最終形態(tài)

(3)當delete父類的指針時,由于子類的析構函數(shù)與父類的析構函數(shù)構成多態(tài),所以得先調動子類的析構函數(shù);之所以再調動父類的析構函數(shù),是因為delete的機制所引起的,delete 父類指針所指的空間,要調用父類的析構函數(shù)。
所以結果就是這樣

以上所述是小編給大家介紹的C++中虛析構函數(shù)的作用及其原理分析詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
C++?STL標準庫std::vector擴容時進行深復制原因詳解
我們知道,std::vector之所以可以動態(tài)擴容,同時還可以保持順序存儲,主要取決于其擴容復制的機制。當容量滿時,會重新劃分一片更大的內存區(qū)域,然后將所有的元素拷貝過去2022-08-08

