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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

虚析构

發布時間:2024/3/12 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 虚析构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

裝載自https://blog.csdn.net/derkampf/article/details/62093252

C++中的虛析構函數到底什么時候有用的,什么作用呢。
一.虛析構函數的作用
總的來說虛析構函數是為了避免內存泄露,而且是當子類中會有指針成員變量時才會使用得到的。也就說虛析構函數使得在刪除指向子類對象的基類指針時可以調用子類的析構函數達到釋放子類中堆內存的目的,而防止內存泄露的.

我們知道,用C++開發的時候,用來做基類的類的析構函數一般都是虛函數??墒?#xff0c;為什么要這樣做呢?下面用一個小例子來說明:

#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析構函數前的virtual去掉,那輸出結果就是下面的樣子了:

沒有調動子類的析構函數
也就是說,類ClxDerived的析構函數根本沒有被調用!一般情況下類的析構函數里面都是釋放內存資源,而析構函數不被調用的話就會造成內存泄漏。我想所有的C++程序員都知道這樣的危險性。當然,如果在析構函數中做了其他工作的話,那你的所有努力也都是白費力氣。
所以,文章開頭的那個問題的答案就是--這樣做是為了當用一個基類的指針刪除一個派生類的對象時,派生類的析構函數會被調用。
當然,并不是要把所有類的析構函數都寫成虛函數。因為當類里面有虛函數的時候,編譯器會給類添加一個虛函數表,里面來存放虛函數指針,這樣就會增加類的存儲空間。所以,只有當一個類被用來作為基類的時候,才把析構函數寫成虛函數。

總結一下虛析構函數的作用:
(1)如果父類的析構函數不加virtual關鍵字
當父類的析構函數不聲明成虛析構函數的時候,當子類繼承父類,父類的指針指向子類時,delete掉父類的指針,只調動父類的析構函數,而不調動子類的析構函數。
(2)如果父類的析構函數加virtual關鍵字
當父類的析構函數聲明成虛析構函數的時候,當子類繼承父類,父類的指針指向子類時,delete掉父類的指針,先調動子類的析構函數,再調動父類的析構函數。
二.虛析構函數的原理分析

#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; }

從創建講起,用gdb調試你會發現,
(1)先調用父類的構造函數,再調用子類的構造函數,

這里有一個問題:父類的構造函數/析構函數與子類的構造函數/析構函數會形成多態,但是當父類的構造 函數/析構函數即使被聲明virtual,子類的構造/析構方法仍無法覆蓋父類的構造方法和析構方法。這是由 于父類的構造函數和析構函數是子類無法繼承的,也就是說每一個類都有自己獨有的構造函數和析構函 數。

(2)而由于父類的析構函數為虛函數,所以子類會在所有屬性的前面形成虛表,而虛表內部存儲的就是父類的虛函數

即使子類也有虛函數,但是由于是單繼承,所以也只有一張虛表,這在上一篇博客多態中講到過。
執行 Base *b = new Der;之后b的最終形態

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

總結

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

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