菱形继承问题分析及其在C++的解决方法(虚继承)
定义
面向对象语言都有一种特性–继承
但存在一种场景(多继承)会掉入陷阱,图示与代码如下:
代码如下
class Person
{
int weight;
public:
int getWeight()
{
return weight;
}
};
class A : public Person {};
class B : public Person {};
class C : public A, public B {};
int main()
{
C c;
int weight = c.getWeight();//此代码不会被任意编译器通过
return 0;
}
如上代码所示,编译器并不会通过以上代码
注释掉报错代码,调试可见
不能通过编译主要包括两方面问题
- 二义性
在对象c调用weight时,如果单继承很简单,但在多继承中,该对象不知道应调用A,B哪一个类下的weight,此为二义性 - 数据冗余
c只需要一个weight,实际上其拥有两个重复的值,此为数据冗余
虽然通过作用域操作符::可以解决,但c++还提供了更主流的解决方案–虚继承
虚继承
通过虚继承,无论该类作为派生类出现多少次,只能继承一个共享的基类子对象 使用时,通过virtual声明继承关系即可
对于以上代码,应将
class A : public Person {};
class B : public Person {};
改成
class A : virtual public Person {};
class B : virtual public Person {};
代码即可通过
值得强调的是
- 虚继承会带来可读性与执行性能的下降
- 虚继承的底层实现牵扯到概念–虚基表,简单解释如下。 执行
sizeof(c),vs 32位输出8
虚继承后输出12,对象c实际空间使用了虚基表
对象c的空间占用,如图
对虚基表更详细的介绍,见另一篇博客。
446

被折叠的 条评论
为什么被折叠?



