為什麼要將基類的析構函式宣告為虛函式

2021-09-30 14:25:36 字數 2440 閱讀 2218

我們大家都知道,在c++ 中,當乙個物件銷毀時,析構函式是用來對類物件和物件成員進行釋放記憶體和做一些其他的cleanup操作。析構函式靠~符號來區分,~ 出現在 析構函式名字的前面,  當我們去定義乙個 虛析構函式時,你只需要簡單的的在~符號前面 加乙個  virtual標誌就可以了。

為什麼需要將析構函式宣告為 虛函式,我們最好用幾個例子來驗證一下,我們首先以乙個 不使用虛析構函式的例子開始,然後我們使用乙個使用析構函式的例子。一旦看到了其中的區別,你就會明白 為什麼需要將析構函式宣告為虛函式。讓我們開始看一下**。

example  without a virtual destructor:

#include using namespace std;

class base

// this is a destructor:

~base()

};class derive: public base

~derive()

};int main()

執行結果如下:

根據上面的輸出,我們可以看到當我們新建乙個指向deriver型別物件指標的時候,建構函式按照由基類到派生類的順序依次呼叫,但是當我們刪除指向deriver 的基類指標時, deriver類中的析構函式沒有被呼叫,而是只呼叫了base的析構函式。(原因可參考:編譯期繫結

執行期繫結

當我們將基類的析構函式宣告為虛函式時

example with a virtual destructor:

我們需要做的就是修改base 類中的析構函式,在~前面加上virtual關鍵字。

class base

// this is a destructor:

virtual ~base()

};

改變之後,執行結果如下:

我們在基類中將析構函式宣告為虛函式,就表示在使用析構函式時,是採用執行期繫結的。那麼delete baseptr的時候執行的是根據baseptr指向的具體型別來呼叫析構函式。

如果你在 派生類中 分配了 記憶體空間的話,沒有將基類的析構函式宣告為虛析構函式,很容易發生記憶體洩漏事件。

例子:

#include using namespace std;

class base

// this is a destructor:

~base()

private:

char *data;

};class derive: public base

~derive()

private:

char *d_data;

};main()

我們在基類和派生類中都個分配了 10個 位元組的空間,這些空間應該由程式設計師來釋放,如果沒有釋放掉的話,就會造成記憶體洩漏。

執行結果如下:

我們可以看到只刪除了基類的分配的空間,這個時候派生類的物件的空間沒有刪除,記憶體洩漏。

另外乙個例子:

#include using namespace std;

class cbase

~cbase()

private:

char *data;

};class cfunction

; ~cfunction(){};

};class cfunctionex : public cfunction

; ~cfunctionex(){};

private:

cbase m_cbase;

};void main()

這裡cfunctionex和cfunction中本身並沒有分配記憶體,應該不會有記憶體洩漏。和上例一樣當刪除pcfun時,它只呼叫了cfunction的析構函式而沒呼叫cfunctionex的析構函式,但cfunctionex本身並沒分配記憶體。所以發生記憶體洩露的地方是m_cbase,因為它是cbase的例項且是cfunctionex成員變數,當cfunctionex的析構函式沒有被呼叫時,當然m_cbase的析構函式也沒有被呼叫,所以cbase中分配的記憶體被洩漏。

解決以上問題的方法很簡單,就是使基類cfunction的析構函式為虛函式就可以了。

這樣就得出乙個結論:當你的基類的析構函式不為虛函式的話,其子類中所有的成員變數的類中分配的記憶體將可能洩漏。將基類的析構函式設為virtual型,則基類的所有派生類的析構函式都會自動設定為virtual型,這保證了任何情況下,都不會出現由於析構函式沒有被呼叫而導致的記憶體洩漏。

為什麼要將類的析構函式宣告為虛函式?

我們知道在類的繼承中,建構函式的執行順序是先構造基類然後再構造派生類,析構函式則相反,是先析構派生類再析構基類。我們也知道宣告父類的指標指向派生類,編譯器會預設實施靜態繫結,不能呼叫派生類重寫的函式,所以才需要虛函式。虛函式是通過虛函式表實現,在執行時進行動態繫結,可以呼叫在派生類重寫的函式。那麼如...

為什麼基類的析構函式宣告為虛函式?

1 作用 在實現多型時,當用基類的指標操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。2 例項 include using namespace std class father father 1 非虛函式 private int mptr class son public father ...

在C 的基類中,析構函式為什麼宣告為虛函式?

在c 的基類中,析構函式為什麼宣告為虛函式,如果不宣告為虛函式時,會發生什麼?奉上 include class base base class derive public base derive int main int argc,tchar argv 執行結果 base create derive...