解構函式virtual與非virtual區別
阿新 • • 發佈:2020-12-25
作為通常的原則,如果一個類定義了虛擬函式,那麼它的解構函式就應當是virtual的。因為定義了虛擬函式則隱含著:這個類會被繼承,並且會通過基類的指標指向子類物件,從而得到多型性。 這個類可能會被繼承,並且會通過基類的指標指向子類物件”,因此基類的解構函式是否為虛將決定子類的物件是否被析構
示例程式碼:
#include <iostream.h> struct A { virtual ~A() {cout<<"~A()\n";} }; struct B: public A { ~B() {cout<<"~B()\n";} }; void main() { A* p = new B; delete p; }
如果A的解構函式不是virtual的,那麼此時就不是先呼叫B的解構函式再呼叫A的解構函式。
Output:
~A();
如果A 的解構函式為virtual,則先~B(),再~A()
Output:
~B();
~A();
類如果會被派生的話,解構函式一般都應該定義為virtual的,主要不是防止記憶體洩露,而是為了正確的析構。如果是個封閉類(即不再被派生),就不要定義為virtual的。虛擬函式畢竟耗費較大的,尤其在記憶體方面。
不用virtual 的幾種情況:
1、作為非公有基類。僅作為 private base class 使用的 class 不需要使用虛擬解構函式
2、不作為介面使用的基類。
4. 如果它的所有派生類(包括派生類的派生類)的解構函式都是trivial的(這裡的trivial指的是在程式設計師的層次什麼事也不做)
5. 如果不需要用基類的指標指向派生類的物件
在這五種情況下,不把解構函式宣告為virtual都是可以的,何況效率會高一些——但前提是你得保證前提的成立——不過這些保證常常是很難100%的:誰能保證別人在派生你的類的時候,解構函式是trivial的,或者別人不用你提供的基類的指標指向派生類物件?這些常常是很難得到保證的。
宣告基類的解構函式為virtual並非總是為了防止memoryleak。另外這也只是作為一般的原則(基類中有虛擬函式則把其解構函式宣告為virtual)。如果你的解構函式什麼事也不作,從效果上來說,不宣告為virtual也無妨。