C++编译警告解决: deleting object of abstract class type ‘xxx‘ which has non-virtual destructor

警告信息:deleting object of abstract class type ‘xxx’ which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]

问题情境

有虚基类A,拥有一个纯虚成员函数func,B类以公共方式继承A:

class A
{
public:
	virtual void func()=0;
};

class B:public A
{
public:
	void func()
	{
		...
	}
}

接着在测试函数中使用基类A指针指向派生类B的实例化对象,并在最后delete该基类指针:

void test()
{
	A* a=new B;
	...
	delete a;
}

上述代码在编译过程中出现开头的警告信息。

错误原因

警告信息中说到我们删除具有非虚析构函数的指针将会导致未定义的行为,我们首先看一下这样会造成什么后果。
我们在虚基类A和派生类B中自定义析构函数在被调用时打印文本信息:

class A
{
public:
	~A()
	{
		cout<<"A类析构"<<endl;
	}
	virtual void func()=0;
};

class B:public A
{
public:
	~B()
	{
		cout<<"B类析构"<<endl;
	}
	void func()
	{
		...
	}
}

在这里插入图片描述

执行完test之后屏幕上只输出了一行“A类析构”,而没有打印“B类析构”的信息。

也就是说,如果基类中的析构函数不是虚函数的话,在销毁指向派生类对象的基类指针时,不会调用派生类的虚构函数,这样就可能出现内存未释放的问题,因此产生警告。

解决方案

正如警告信息所说的,我们应将基类的析构函数写为虚析构,但注意,虚析构函数是不可以只声明而不定义的,所以我们不能将基类的虚析构函数仅仅写为virtual ~A()=0;而不实现,可以这样写:

class A
{
public:
	virtual ~A()
	{
		cout<<"A类析构"<<endl;//删掉这一句改为空实现也可以
	}
	virtual void func()=0;
};

(或者类内定义virtual ~A()=0;,并在类外空实现也是可以的。)

我们再次执行测试函数:
在这里插入图片描述

这时可以看到基类和派生类的析构函数全部调用,警告解决。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值