C++学习笔记:多继承及其二义性问题、虚继承
作者:互联网
C++学习笔记:多继承及其二义性问题
1.多继承
多继承就是一个子类有多个父类。
在继承中,子类会继承父类的成员变量和成员函数:
class A
{
public:
int a;
void print(void){cout<<"a = "<<this->a<<endl;}
};
class C:public A
{};
int main(int argc,char**argv)
{
C c;
c.a=5;
c.print();
return 0;
}
输出:
a = 5
上面是单继承的情况,C类很好继承了A类的print()
方法,多继承和单继承的原理、效果并无明显区别,但是多继承会导致二义性问题,来看这样一种情况,假如C类继承自A类和B类,且B类中也有一个print()
方法,这个时候C该继承哪一个呢?
不妨写代码测试一下:
class A
{
public:
int a;
void print(void){cout<<"a = "<<this->a<<endl;}
};
class B
{
public:
int b;
void print(void){cout<<"b = "<<this->b<<endl;}
};
class C:public A,public B
{
};
int main(int argc,char**argv)
{
C c;
c.a=5;
c.print();
return 0;
}
结果是编译报错了,对于编译器来说,print()
是模糊有歧义的:
main.cpp:98:4: error: request for member ‘print’ is ambiguous
c.print();
多继承的二义性问题有2种情况。
2.多继承的二义性问题情况1
场景1:C多继承自A和B,则C中调用A和B的同名成员时会有二义性。
原因分析:C从A和B各自继承了一个同名(但是不同namespace
域)成员,所以用C的对象来调用时编译器无法确定到底想调用的是哪一个。
解决办法:
- ①避免出现同名方法,让A和B的
public
成员命名不要重复冲突。但这个有时不可控,比如A和B类都是别人提供的,当另外的人使用C类想继承A,B两个类的时候,还得去找提供这个两个类的人,你俩谁行行好,把print()
重命名一下。 - ②编码时明确指定要调用哪一个,用
c.A::print()
明确指定调用的是A的print()
而不是B的,这就类似于2个人叫张三,在外面高的就叫大张三,矮的叫小张三。 - ③在C中重定义
print()
,则调用时会调用C中的print()
,A和B中的都被隐藏了。
总结:能解决,但是都没有很好的解决。
3.多继承的二义性问题情况2
场景2:菱形继承问题。即A为祖类,B1:A, B2:A, C:B1,B2,此时用C的对象调用A中的某个方法时会有二义性。
原因分析:c.print()
有二义性,c.A::print()
也有二义性,但是c.B1::print()
和c.B2::print()
却没有二义性。
解决办法:和情况1中的一样,但是情况2更隐蔽,也更难以避免。
4.多继承的二义性问题情况总结
二义性就是歧义,好的情况表现为编译错误,不好的情况表现为运行时错误,最惨的情况表现为运行时莫名其妙.随着系统规模的变大和逻辑变复杂,难免出现二义性,这是系统自身带来的。
解决二义性问题不能靠写代码的人个人的细心和调试能力,而要靠机制,也就是编程语言的更高级语法特性。虚函数、虚继承、纯虚函数、抽象类、重写覆盖、多态等概念就是干这些事的。
5.虚继承解决菱形继承的二义性问题
5.1 虚继承怎么用
场景:菱形继承导致二义性问题,本质上是在孙子类C中有B1和B2中包含的2份A对象,所以有了二义性。
虚继承解决方案:让B1和B2虚继承A,C再正常多继承B1和B2即可。
class A
{
public:
int a;
void print(void){cout<<"a = "<<this->a<<endl;}
};
class B1:virtual public A
{
//A::print()
};
class B2:virtual public A
{
//A::print()
};
class C:public B1,public B2
{
//B1::A::print()
//B2::A::print()
};
虚继承就这么简单,就是为了解决菱形继承的二义性问题而生,和虚函数(为了实现多态特性)并没有直接关系。
5.2 虚继承的实现原理
虚继承的原理是:虚基类表指针vbptr
和虚基类表virtual table
。
标签:二义性,继承,void,C++,B1,B2,print 来源: https://blog.csdn.net/PecoHe/article/details/113307845