析构函数virtual与非virtual区别
作為通常的原則,如果一個類定義了虛函數,那么它的析構函數就應當是virtual的。因為定義了虛函數則隱含著:這個類會被繼承,并且會通過基類的指針指向子類對象,從而得到多態性。?? 這個類可能會被繼承,并且會通過基類的指針指向子類對象”,因此基類的析構函數是否為虛將決定子類的對象是否被析構
示例代碼:
 
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、不作為接口使用的基類。?? 
 ? 3.?? 如果你可以保證這個類不被public繼承(private/protected繼承的話,在非friend函數/類中就無法用基類指針指向派生類了)?? 
 ? 4.?? 如果它的所有派生類(包括派生類的派生類)的析構函數都是trivial的(這里的trivial指的是在程序員的層次什么事也不做)?? 
 ? 5.?? 如果不需要用基類的指針指向派生類的對象?? 
 ? 在這五種情況下,不把析構函數聲明為virtual都是可以的,何況效率會高一些——但前提是你得保證前提的成立——不過這些保證常常是很難100%的:誰能保證別人在派生你的類的時候,析構函數是trivial的,或者別人不用你提供的基類的指針指向派生類對象?這些常常是很難得到保證的。??
聲明基類的析構函數為virtual并非總是為了防止memory?? leak?? 另外這也只是作為一般的原則(基類中有虛函數則把其析構函數聲明為virtual)。如果你的析構函數什么事也不作,從效果上來說,不聲明為virtual也無妨
 
 
 
 
#include <iostream>
using namespace std;class Base{public:virtual ~Base() {cout<<"~B"<<endl;} };class Derived:public Base{public:virtual ~Derived() {cout<<"~D"<<endl;} };int main (){Base *b=new Derived;delete b; } ? 復制代碼?以上代碼執行結果是:
~D
~B
?
對于析構函數使用虛函數的解釋,是這樣的,因為是使用語句 Base *b=new Derived;來創建的對象b,如果,我們不把析構函數聲明為虛函數,那么實際上,在對象生命周期結束時,調用的將只是基類Base的析構函數,而派生類Derived的析構函數將是不調用的,你可以試驗一下,此時,只打印~B。而我們為了正確地釋放對象,所以要將析構函數聲明為虛函數,這時,基類和派生類的析構函數就都會調用了。總結
以上是生活随笔為你收集整理的析构函数virtual与非virtual区别的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: nm命令中符号类型详解
 - 下一篇: 电脑怎样执行编程语言的?