2010.7.29 为什么析构函数设计成虚函数?

首先必须明白,声明成虚函数,必须是在有继承关系的几个类中,才有意义。

当声明了一个基类(CBase),和一个继承类时(CSubDevice::CBase)时,基类有自己的成员需要用析构释放内存,继承类也有自己的成员需要释放内存。

如何用一个基类的指针,指向了一个子类的对象,那么当释放基类指针指向的堆内存时,假如这时候析构函数没有使用虚函数,那么程序只会调用基类的析构函数,这时,子类的特有的内存没有释放,造成了内存泄漏。

如下:

class CDevice
{
public:
 CDevice(void);
public:
 ~CDevice(void);
};

class CBase
{
public:
 CBase(void);
public:
 ~CBase(void);
public:
 CDevice* pDevice;//需要在析构中释放 1
};

class CSubDevice:public CBase
{
public:
 CSubDevice(void);
public:
 ~CSubDevice(void);
public:
 CString *pCstr; //需要在析构中释放  2
};

 

假如有这样一个对象:

CBase* pBase=new CSubDevice();

那么释放的时候,即Delete pBase时,只调用了~CBase(),  2处没有调用造成了内存泄漏(pCstr没有被释放)

 

怎么解决呢?

假如定义~CBase(void);
为虚函数,即Virtual ~CBase(void),如下

 

class CDevice
{
public:
 CDevice(void);
public:
 ~CDevice(void);
};

class CBase
{
public:
 CBase(void);
public:
 Virtual  ~CBase(void);
public:
 CDevice* pDevice;//需要在析构中释放 1
};

class CSubDevice:public CBase
{
public:
 CSubDevice(void);
public:
 Virtual  ~CSubDevice(void);
public:
 CString *pCstr; //需要在析构中释放  2
};

 在这种情况下,如下:

CBase* pBase=new CSubDevice();

那么释放的时候,即Delete pBase时,不仅调用了~CBase,还调用了~CSubDevice。实际上是先调用了~CSubDeivce,然后调用了~CBase;

 

如果是CSubDevice* pBase=new CSubDevice();

那么释放的时候,即 Delete pBase时,先调用了~CSubDeivce,然后调用了~CBase;

 

在以上两种情况下,不管~CSubDevice中有没有代码,都会被调用,哪怕是空的函数体。

 

如果是CBase* pBase=new CBase()呢?

只会调用~CBase()

 

 

 

 

posted @ 2010-07-29 22:33  pjh123  阅读(229)  评论(0)    收藏  举报