1. 程式人生 > 其它 >C++為什麼要將解構函式設為虛擬函式

C++為什麼要將解構函式設為虛擬函式

技術標籤:C++學習筆記面試

首先我們知道虛擬函式是實現執行期的多型的。
根據型別相容原則,在需要基類指標的地方,都可以用派生類的指標去代替。

如下程式碼,就實現了多型。

#include<bits/stdc++.h>
using namespace std;
class A{
    public:
        A(){

        }
        ~A(){
        }
        virtual void fun(){
            cout<<1<<endl;
        }
};
class B:public A{
public: B(){ } ~B(){ } virtual void fun(){ cout<<2<<endl; } }; int main(){ A* testA=new A(); testA->fun(); delete testA; A* testB=new B(); testB->fun(); delete testB; return 0; }

輸出:
在這裡插入圖片描述

其實,上面程式碼是存在記憶體洩漏的。

我們把類A和類B的解構函式加上輸出看看

#include<bits/stdc++.h>
using namespace std;
class A{
    public:
        A(){

        }
        ~A(){
            cout<<"A over"<<endl;
        }
        virtual void fun(){
            cout<<1<<endl;
        }
};
class B:public A{
    public:
B(){ } ~B(){ cout<<"B over"<<endl; } virtual void fun(){ cout<<2<<endl; } }; int main(){ A* testA=new A(); testA->fun(); delete testA; cout<<endl; A* testB=new B(); testB->fun(); delete testB; return 0; }

輸出:
在這裡插入圖片描述
可以發現testA沒有問題。
但是testB只有類A部分被析構了,而類B還沒有析構,這裡存在了記憶體洩漏

那麼將解構函式定義為虛擬函式後呢


#include<bits/stdc++.h>
using namespace std;
class A{
    public:
        A(){

        }
        virtual ~A(){
            cout<<"A over"<<endl;
        }
        virtual void fun(){
            cout<<1<<endl;
        }
};
class B:public A{
    public:
        B(){

        }
        virtual ~B(){
            cout<<"B over"<<endl;
        }
        virtual void fun(){
            cout<<2<<endl;
        }

};
int main(){
    A* testA=new A();
    testA->fun();
    delete testA;
    cout<<endl;
    A* testB=new B();
    testB->fun();
    delete testB;
    return 0;
}

輸出:
在這裡插入圖片描述

這樣就沒有問題了

所以,將解構函式設為虛擬函式,是為了防止記憶體洩漏。

如果存在用基類指標指向派生類物件,這樣子可以使得基類和派生類的解構函式都被呼叫,不會造成記憶體洩漏。如果不把解構函式定義為虛擬函式,那麼只會呼叫基類的解構函式。