c++ 多重继承歧义及其解决办法

        关于c++中多重继承该不该使用的争论不是我们关注的问题,但是现实世界很多模型确实是多重继承类别。和单一继承相比,它比较复杂,也不太好理解,而且多基派生可能会引起二义性。下面我们就说说多重继承可能的二义性和解决办法。

       先看看没有共同基类的多基派生如何引起二义性。这种继承大致如图所示

这时候有个问题就是假如两个基类有同名的成员,编译器就无法知道要访问哪一个类的成员了,解决的方法就是加上作用域限定符,准确告诉编译器这个成员属于哪个类中的。用一个非常简单的例子代码演示下

#include <iostream>

using namespace std;

class Base1 {
public:
	int i;
};

class Base2 {
public:
	int i;
};


class Derived : public Base1, public Base2 {

};

int main() {

	Derived d;
	
	//下面这样的用法就会产生错误,编译器不知道i到底属于哪个基类
	//d.i = 1;
	
	//加上类名限定符解决
	d.Base1::i = 1;
	d.Base2::i = 2;

	system("pause");

	return 0;
}
        还有一个多基派生的情况就是含有共同基类(所谓的菱形继承)。

        类似于这种继承,由于Base1和Base2都继承Base,那Base中的成员会被拷贝到两个派生类中,这时候Derived又同时继承Base1和Base2,要是使用基类的成员,就是出现二义性,编译器无法准确知道成员到底属于谁。这种歧义的解决方法是继承的时候将继承自共同基类声明为virtual公有继承。这就是虚基类,这样引用中就只有一份基类的成员拷贝了。还是一个非常简单的例子

#include <iostream>

using namespace std;

class Base {
public:
	int i;
};

class Base1 : virtual public Base {
public:
	int j;
};

class Base2 : virtual public Base {
public:
	int k;
};


class Derived : public Base1, public Base2 {
public:
	int sum;
};

int main() {

	Derived d;
	
	d.i = 1;
	d.j = 2;
	d.k = 3;

	d.sum = d.i + d.j + d.k;
	cout << d.sum << endl;
	

	system("pause");

	return 0;
}
        那到底是如何实现的呢,先看看有共同基类派生时,不使用virtual的派生类大小,代码及运行结果看图

        可以看出来,派生类Derived包含了Base1中的一个int 变量和Base1继承自Base中的一个int 变量,同样也包含了Base2中的一个int 变量和Base2继承自Base中的一个int 变量,所以Derived含有4个int变量,32位机器上正好是16个字节。

        在看看使用虚基类的情况,看图吧

        这种情况的对象内存布局大概是这样


        Base1中应该含有一个指向Base对象4字节虚指针和自己的的一个int变量4字节,就是8字节,同样的原理Base2也应该是8字节,派生类Derived应该是20字节=两个基类的16字节+共同基类4字节。


        多重继承要比单一继承复杂,可能会出现二义性。所以在Java语言中使用接口代替了多重继承。在c++中多重继承主要用于接口继承,接口继承仅仅是在一个派生类中加入了成员函数的声明,貌似Java就是这样的,但是c++并不支持这种做法,因为在c++中所有的继承都是实现继承,但是可以模拟实现,首先声明一个接口类,类中只有声明,没有成员数据和函数体,而且除了虚析构函数外,其余的函数都是纯虚函数,然后从这个接口类派生一个子类并实现基类中声明的函数体。关于实现继承、接口继承和可视继承会在以后有空写文章来介绍下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值