继承和多态二:虚析构函数
生活随笔
收集整理的這篇文章主要介紹了
继承和多态二:虚析构函数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
雖然我們已經知道了什么是繼承和多態,也明白了多態依賴于繼承,但是在多態中存在哪些問題呢?
多態中可能存在的內存泄露問題
例如下面的程序中,在圓形Circle的類中定義一個圓心的坐標,并且坐標是在堆中申請的內存,則在mian函數中通過基類指針操作派生類對象的成員函數是沒有問題的,可是在銷毀對象內存的時候則只是執行了基類的析構函數,派生類的析構函數卻沒有執行,這會導致內存泄漏。換句話說如果delete后邊跟基類的指針則只會執行基類的析構函數,如果delete后面跟的是派生類的指針,那么它即會執行派生類的析構函數,也會執行基類的析構函數
class Shape { public:virtual double calcArea(){...}//虛函數 Shape();~Shape();.... private:.... }; Shape::Shape() { cout<<"class Shape was created"<<endl; } Shape::~Shape() { cout<<"class Shape was deleted"<<endl; } class Circle:public Shape { public:Circle(int x,int y,double r);~Circle();virtual double calcArea();//此處可不加virtual,但系統默認加上 .... private:double m_dR;Coordinate *m_pCenter; //坐標類指針 .... }; Circle::Circle(int x,int y,double r) {m_pCenter=new Coordinate(x,y);m_dR=r;cout<<"class Circle was created"<<endl; } Circle::~Circle() {delete m_pCenter;m_pCenter=NULL;cout<<"class Circle was deleted"<<endl; } .... int main() {Shape *shape1=new Circle(5,6,4.0);//基類對象,改成Circle *circle=new Circle(5,6,4.0)則為派生類對象shape1->calcArea();delete shape1;shape1=NULL;//派生類對象的內存未回收return 0; } 打印結果可見,派生類的析構函數并沒有被執行,而只是回收了開辟給基類對象的空間,那如何解決這個問題呢,固然可以通過delete派生類對象實現,除此之外,還可以引入虛析構函數,你看普通的虛函數都可以實現多態的動態聯編,那對于析構函數呢?虛析構函數也會在最后對象銷毀內存時動態鏈接到派生類對象。 可以這樣解釋它:如果基類當中定義了虛析構函數,那么基類的虛函數表當中就會有一個基類的虛析構函數的入口指針,指向的是基類的虛析構函數,派生類的虛函數表當中也會產生一個派生類的虛析構函數的入口指針,指向的是派生類的虛析構函數,這個時候使用基類的指針指向派生類的對象,delete掉基類指針,就會通過指向的基類的對象找到基類的虛函數表指針,從而找到虛函數表,在虛函數表中找到派生類的虛析構函數,從而使得派生類的析構函數得以執行,派生類的析構函數執行之后系統會自動執行父類的虛析構函數。即整個執行過程是:virtual關鍵字可以修飾普通的成員函數,也可以修飾析構函數,但并不是沒有限制
virtual在函數中的使用限制
-
- 普通函數不能是虛函數,也就是說這個函數必須是某一個類的成員函數,不可以是一個全局函數,否則會導致編譯錯誤。
- 靜態成員函數不能是虛函數 static成員函數是和類同生共處的,他不屬于任何對象,使用virtual也將導致錯誤。
- 內聯函數不能是虛函數 如果修飾內聯函數 如果內聯函數被virtual修飾,計算機會忽略inline使它變成存粹的虛函數。(inline將會在后面的博客中介紹)
- 構造函數不能是虛函數,否則會出現編譯錯誤。
轉載于:https://www.cnblogs.com/cvtoEyes/p/8492247.html
總結
以上是生活随笔為你收集整理的继承和多态二:虚析构函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tomcat启动时项目重复加载,导致资源
- 下一篇: DataPipeline | PayPa