虚继承的原理

举报
芒果_Mango 发表于 2022/07/31 23:32:54 2022/07/31
【摘要】 虚继承的原理C++编译器是如何通过虚继承解决数据冗余和二义性的呢?1.通过监视窗口已经看不到真实的存在,因为监视窗口被编译器处理过2.建议使用内存窗口来进行查看虽然虚继承补了菱形继承的坑,但是也付出了很大的代价, 1.对象模型更复杂了,学习理解成本很高 2.有一定的效率影响虚拟继承解决数据冗余和二义性的原理 为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象...

虚继承的原理

C++编译器是如何通过虚继承解决数据冗余和二义性的呢?

1.通过监视窗口已经看不到真实的存在,因为监视窗口被编译器处理过

2.建议使用内存窗口来进行查看

虽然虚继承补了菱形继承的坑,但是也付出了很大的代价, 1.对象模型更复杂了,学习理解成本很高 2.有一定的效率影响


虚拟继承解决数据冗余和二义性的原理 为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成员的模型。

image-20220313101142212

未使用虚继承:

class A
{
public:
    int _a;
};
class B : public A
{
public:
    int _b;
};
class C : public A
{
public:
    int _c;
};
class D : public B, public C
{
public:
    int _d;
};
int main()
{
    D d;
    d.B::_a = 1;
    d.C::_a = 2;
    d._b = 3;
    d._c = 4;
    d._d = 5;
    return 0;
}

未使用虚继承

下图是菱形继承的内存对象成员模型:这里可以看到数据冗余

image-20220311212146687

image-20220313102612176

先继承B,再继承C 我们也可也看出, 先继承的在前面,后继承的在后面,

这里就可以看出为什么菱形继承导致了数据冗余和二义性,根本原因就是D类对象当中含有两个_a成员。


使用虚拟继承后

image-20220313102534200

class A
{
public:
    int _a;
};
class B : virtual public A
{
public:
    int _b;
};
class C : virtual public A
{
public:
    int _c;
};
class D : public B, public C
{
public:
    int _d;
};
int main()
{
    D d;
    d.B::_a = 1;
    d.C::_a = 2;
    d._b = 3;
    d._c = 4;
    d._d = 5;
    return 0;
}

image-20220313105402108

其中D类对象当中的_a成员被放到了最后,而在原来存放两个_a成员的位置变成了两个指针,这两个指针叫虚基表指针,它们分别指向一个虚基表。 虚基表中包含两个数据,第一个数据是为多态的虚表预留的存偏移量的位置(这里我们不必关心),第二个数据就是当前类对象位置距离公共虚基类的偏移量。 也就是说,这两个指针经过一系列的计算,最终都可以找到成员_a

注意:虚基表中存的是相对地址

image-20220313105551978


下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下面,这个A 同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指 针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。

image-20220311212159114


下面是上面的Person关系菱形虚拟继承的原理解释:

image-20220311212216501


若是将D类对象赋值给B类对象,在这个切片过程中,就需要通过虚基表中的第二个数据找到公共虚基类A的成员,得到切片后该B类对象在内存中仍然保持这种分布情况

子给父 -> 切片

int main()
{
    D d;
    d.B::_a = 1;
    d.C::_a = 2;
    d._b = 3;
    d._c = 4;
    d._d = 5;B b = d;//切片行为
    return 0;
}

image-20220313110545549

_a对象仍然存储在该B类对象的最后


只要有公共的祖先类就是菱形继承

例如:

image-20220430163058152


【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。