虚析构函数-C++复习三

虚析构函数-C++复习三

引出问题

通常,我们在类的析构函数中删除一些在堆上申请的内存,以释放不断增长的内存空间.虚函数声明语法如下:

~type_name();

假设有个类child,从base类派生而来,并且child类使用多态技术实现了方法func, 同时child包含了一个char指针成员,在child的构造函数中使用new操作符创建该成员变量,代码如下:

class base
{
	public:
		base()
		{
			cout<<"base constructor invoked"<<endl;
		}
		
		~base()
		{
			cout<<"base destructor invoked"<<endl;
		}
		virtual void func()
		{
			cout<<"base func invoked"<<endl;
		}
	private:
};

class child : public base
{
	public:
		child()
		{
			cout<<"child constructor invoked"<<endl;
			m_pBuf = new char[1024];
		}
		~child()
		{
			cout<<"child destructor invoked"<<endl;
			delete []m_pBuf;
		}
		virtual void func()
		{
			cout<<"child func invoked"<<endl;
		}
	private:
		char *m_pBuf;
};

int main()
{
	{
		base *pObj = new child();
		pObj->func();
		
		delete pObj;
	}
	return 0;
}

输出如下:
在这里插入图片描述
程序说明:
在main中,我们创建了派生类child的对象,并让基类base的指针指向它,以达到多态的目的,当我们不需要这个对象时,使用delete操作符将pObj删除,但是,pObj对象销毁时,并没有调用child类的析构函数,只是调用了基类的析构函数.从而导致了派生类成员m_pBuf不能删除,发生了内存泄露.
当然有些友好的编译器可能会发出警告,指出基类没有将析构函数声明为virtual的害处,如:

=== Build: Debug in virtualdestructor (compiler: GNU GCC Compiler) ===|
/root/projects/cpp/virtualdestructor/main.cpp||In function ‘int main()’:|
/root/projects/cpp/virtualdestructor/main.cpp|51|warning: deleting object of polymorphic class type ‘base’ which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]|

分析

在C++中,new 和 delete对象的类型必须一致,而这个规定对类派生却是意外,允许delete指向派生类对象的基类指针.
但是,调用的是基类的析构函数,除非我们将基类的析构函数声明为virtual,否则派生类的析构函数将不会被调用.也就是说,只有将基类的析构函数声明为virtual,程序才能按正确的顺序执行析构函数(先执行派生类的析构函数,再执行基类的析构函数).

解决办法

将基类的虚函数声明为virtual,如

virtual ~base();

结论

在实现类时,总是将类的析构函数声明为虚函数是有益处的,如果类没有被派生,也没有什么害处.而如果有派生类,就有可能发生内存泄露!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值