C 將析構函式定義成virtual的原因

2021-08-07 06:42:58 字數 1172 閱讀 2907

疑問:為什麼在c++的實際使用中繼承子類的虛構函式有的時候需要新增virtual有時候不需要新增virutal

1. 一般來說,如果乙個類要被另外乙個類繼承,而且用其指標指向其子類物件時,例如:

a* d = new b();(假定a是基類,b是從a繼承而來的派生類)

那麼其(a類)析構函式必須是虛的,否則在delete d時,b類的析構函式將不會被呼叫,因而會產生記憶體洩漏和異常; 

2. 在構造乙個類的物件時,先構造其基類子物件,即呼叫其基類的建構函式,然後呼叫本類的建構函式;銷毀物件時,先呼叫本類的析構函式,然後再呼叫其基類的建構函式;

舉個例子:

#include "stdio.h"

#include

class animal

virtual void foo()

virtual ~animal()

};class dog : public animal

virtual void foo()

virtual ~dog()

};int main(int argc,char* argv)

**輸出如下:

delete pa 實際上相當於:pa->~animal();釋放pa所指向的記憶體(或許是free(pa))。

在這裡,因為~animal()是virtual的,儘管是通過animal型別的指標呼叫的,根據v-table的資訊,~dog()被正確呼叫到。如果把virtual屬性去掉,那麼被呼叫的是~animal(),dog類的建構函式被呼叫而析構函式未被呼叫,建構函式中分配的資源沒有釋放,從而產生了記憶體洩漏。析構函式預設宣告為virtual,就可以避免這一問題。

如果把**中的紅色的「virutual」(基類animal析構函式前的virtual)刪除的話,輸出如下:

明顯dog的析構函式沒有被呼叫,記憶體洩漏了

可另乙個問題是,有時virtual是不需要的。如果乙個類不會被繼承,比如乙個utility類,該類完全是靜態方法;或者一些類儘管可能會被繼承,但不會被使用成多型的,即除了析構函式外,沒有其他的方法是virtual的,這時就可以把virtual屬性去掉。

去掉析構函式的virtual屬性後,因為該類中沒有其他的virtual函式,所以編譯時不會生成v-table,這樣就節省了編譯時間,並減少了最終生成的程式的大小。更重要的是,遵從這一規則,給該類的維護者乙個資訊,即該類不應被當作多型類使用。

C 將析構函式定義成virtual的真正原因

1.一般來說,如果乙個類要被另外乙個類繼承,而且用其指標指向其子類物件時,如題目中的a d new b 假定a是基類,b是從a繼承而來的派生類 那麼其 a類 析構函式必須是虛的,否則在delete d時,b類的析構函式將不會被呼叫,因而會產生記憶體洩漏和異常 2.在構造乙個類的物件時,先構造其基類子...

C 中析構函式定義成虛函式的原因

為什麼標準c 建議將虛構函式定義成虛函式,下面就來 這個問題。include class base base private char data class baseex public base baseex private char m data void main 很顯然,上述的程式有記憶體洩漏...

C 中析構函式定義成虛函式的原因

為什麼標準c 建議將虛構函式定義成虛函式,下面就來 這個問題。include class base base private char data class baseex public base baseex private char m data void main 很顯然,上述的程式有記憶體洩漏...