《C++避坑神器·六》多继承下问题处理(同名变量,信号槽,多态内存释放)

本文主要介绍C++多继承存在的问题及解决办法。多继承可能出现二义性错误,需加父类作用域区分;QT的moc文件只认多继承列表中的第一个父类,信号槽失效时需检查位置。此外,还阐述了父类析构不加virtual导致程序崩溃的原因及加虚析构函数后正常运行的原理。

文章目录

概要

多继承踩过的坑看这一篇就够~

技术细节

1、多继承下同名变量问题处理:

class Base1
{
public:
	Base1() :A(10) {}
	int A;
};

class Base2
{
public:
	Base2() :A(100) {}
	int A;
};

class Son : public Base1, public Base2
{
};

int main()
{
	Son s;
	//s.A;      //两个父类都有A,不知道调用哪个父类的A,出现二义性错误
	s.Base1::A; //10
}

多继承存在一个问题就是可能多个父类有相同的成员变量,那么子类直接调用父类变量时就不知道调用哪个父类的变量,出现二义性错误,这时候必须加父类作用域进行区分。

2、多继承下信号槽问题:
QT的moc文件只认多继承列表中的第一个父类,如果使用过程中出现信号槽失效的问题,需要查看包含信号槽的父类是否放在多继承列表中的第一个位置。

3、多继承下的多态内存释放问题:易错!!!

class Animal1
{
public:
	virtual void fun1() = 0;
	~Animal1()
	{
		cout << "Animal1析构" << endl;
	}
};

class Animal2
{
public:
	virtual void fun2() = 0;
	~Animal2()
	{
		cout << "Animal2析构" << endl;
	}
};

class cat : public Animal1, public Animal2
{
public:
	virtual void fun1() {}
	virtual void fun2() {}
	~cat()
	{
		cout << "cat析构" << endl;
	}
};

int main()
{
	Animal1* animal1 = new cat();
	Animal2* animal2 = new cat();
	delete animal1;
	delete animal2;
}

如果直接运行程序,在执行到delete animal2时程序会出现如下崩溃:
在这里插入图片描述
解决办法:父类析构加上virtual变为虚析构,打印如下:
在这里插入图片描述

原因:
如果父类析构不加virtual,delete animal1时是没有错误的,错误出现再delete animal2。原因很好猜到,animal1所指的地址就是Cat对象的首地址,所以delete animal1可以正常运行;但是animal2 所指的地址不是Cat对象的首地址,由于这里是多继承(除了第一个父类,后面继承的父类地址相对于子类有偏移),animal2所指的地址相对Cat对象的首地址有偏移,编译器发现它自己没有给这个地址分配空间,所以就报错了。
为什么加了虚析构函数后运行正常呢?原因也很简单,delete这个运算符,是先调用析构函数,再回收内存。前面是没有虚析构函数,但animal1指向Cat首地址所以能顺利释放内存,animal2指向地址相对Cat首地址有偏移,现在加了虚析构函数(普通析构无法修改偏移地址),在虚析构函数结束时会把偏移过的地址改回原样,地址对了回收内存自然也对了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦回阑珊

一毛不嫌多,一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值