基類的析構(gòu)函數(shù)為什么要設(shè)成虛函數(shù)
#include <iostream.h>
class A
{
public:
A(){cout<<"A()\n";}
~A(){cout<<"~A()\n";}
};
class B : public A
{
public:
B(){cout<<"B()\n";}
~B(){cout<<"~B()\n";}
};
void main()
{
A * p = new B();
delete p ;
}
輸出結(jié)果:
A()
B()
~A()
============================================================
在基類的析構(gòu)函數(shù)前添加virtual改編后的代碼:
#include <iostream.h>
class A
{
public:
A(){cout<<"A()\n";}
virtual ~A(){cout<<"~A()\n";}
};
class B : public A
{
public:
B(){cout<<"B()\n";}
~B(){cout<<"~B()\n";}
};
void main()
{
A * p = new B();
delete p ;
}
輸出結(jié)果:
A()
B()
~B()
~A()
=================================================================
如果不是在基類的析構(gòu)函數(shù)前添加virtual,而是在子類的析構(gòu)函數(shù)前添加virtual,則編譯不會出錯,但是運行會出錯。如果在此基礎(chǔ)上再把“delete p;”這句話給注釋了,那依然不會運行出錯,不過這就不符合變成規(guī)范了,只要是我們自己用new創(chuàng)建的東西,我們就必須在適當(dāng)?shù)奈恢蔑@示的調(diào)用delete來刪除。
=================================================================
如果再添加一個中間類,代碼如下:
#include <iostream.h>
#include <windows.h>
class A
{
public:
A(){cout<<"A()\n";}
virtual ~A(){cout<<"~A()\n";}
};
class B : public A
{
public:
B(){cout<<"B()\n";}
virtual ~B(){cout<<"~B()\n";}
};
class C : public B
{
public:
C(){cout<<"C()\n";}
~C(){cout<<"~C()\n";}
};
void main()
{
A * p = new C();
delete p ;
}
輸出結(jié)果為:
A()
B()
C()
~C()
~B()
~A()
析構(gòu)函數(shù)前添加virtual,必須要在最最根上的基類的析構(gòu)函數(shù)前添加,不能再B類或C類的析構(gòu)函數(shù)前添加,只要A類的析構(gòu)函數(shù)添加了virtual,從A類派生的類都不必在自己的析構(gòu)函數(shù)前添加virtual了。
所以如果沒有虛析構(gòu)函數(shù)的話, 那么子類中特有的部分就不會被釋放, 造成"經(jīng)典"的釋放一半, 泄露一半的內(nèi)存泄露.
posted on 2008-02-23 19:17 so true 閱讀(1784) 評論(0) 編輯 收藏 所屬分類: C&C++