[C++]多继承与二义性问题

本文探讨了C++中的多继承概念,解释了如何引发二义性问题,特别是在菱形继承场景下。文章详细阐述了二义性的解决方法,包括避免命名冲突、使用作用域解析运算符以及在派生类中重定义函数。此外,还介绍了虚继承作为解决菱形继承问题的关键,解释了虚继承的实现原理,涉及虚基类表和虚基类表指针。通过这些方法,可以有效地解决多继承带来的复杂性和潜在问题。
摘要由CSDN通过智能技术生成

1. 什么是多继承?

多继承就是一个子类有多个父类,如下代码示例。

class C:public A, public B
{
};

2. 多继承会导致二义性问题

(1)场景1:多继承的二义性

C多继承自A和B,则C中调用A和B的同名成员时会有二义性。

原因:C从A和B各自继承了一个同名(不同namespace域)成员,所以用C的对象来调用时编译器无法确定我们想调用的是哪一个。

//基类 A
class A{
public:
    void set(int a);
};

//基类 B
class B{
public:
    void set(int a);
};

//派生类 C
class C:public A, public B
{
}

// main.cpp
int main()
{
    c.set();    //编译报错,set()有二义性,编译器不知其来自A还是来自B
}


解决方法:

解决办法1:避免出现,让A和B的public成员命名不要重复冲突。但这个有时不可控。

解决办法2:编码时明确指定要调用哪一个,用 c.A::func() 明确指定调用的是 class A 的 func 而不是 class B 的。

解决办法3:在 C 中重定义 func,则调用时会调用 C 中的 func,A 和 B 中的都被隐藏了。

(2)场景2:菱形继承问题

 即A为祖类,B1:A, B2:A, C:B1,B2,此时用C的对象调用A中的某个方法时会有二义性。

分析:c.func()有二义性,c.A::func()也有二义性,但是c.B1::func()和c.B2::func()却没有二义性。

解决办法:和问题1中的一样,但是问题2更隐蔽,也更难以避免。

3. 虚继承解决菱形继承的二义性问题

菱形继承导致二义性问题,本质上是在孙子类C中有B1和B2中包含的2份A对象,所以有了二义性。

虚继承解决方案:让B1和B2虚继承A,C再正常多继承B1和B2即可。

class B1: virtual public A
{
	// A::set
};

class B2:virtual public A
{
	// A::set
};

class D:public B1, public B2
{
	// B1,B2为虚继承A,则D继承B1, B2时,只会继承了一个A类的函数,C++天然地优化掉其中一个A类的函数
};

4. 虚继承的实现原理

虚继承的原理是:虚基类表指针vbptr和虚基类表virtual table

参考:https://blog.csdn.net/xiejingfa/article/details/48028491

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值