当前位置:网站首页>虚继承的原理
虚继承的原理
2022-07-31 23:34:00 【华为云】
虚继承的原理
C++编译器是如何通过虚继承解决数据冗余和二义性的呢?
1.通过监视窗口已经看不到真实的存在,因为监视窗口被编译器处理过
2.建议使用内存窗口来进行查看
虽然虚继承补了菱形继承的坑,但是也付出了很大的代价, 1.对象模型更复杂了,学习理解成本很高 2.有一定的效率影响
虚拟继承解决数据冗余和二义性的原理 为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成员的模型。

未使用虚继承:
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;}未使用虚继承
下图是菱形继承的内存对象成员模型:这里可以看到数据冗余


先继承B,再继承C 我们也可也看出, 先继承的在前面,后继承的在后面,
这里就可以看出为什么菱形继承导致了数据冗余和二义性,根本原因就是D类对象当中含有两个_a成员。
使用虚拟继承后

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

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

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

若是将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;}
_a对象仍然存储在该B类对象的最后
只要有公共的祖先类就是菱形继承
例如:

边栏推荐
- What is customer profile management?
- 网络安全--通过握手包破解WiFi(详细教程)
- /etc/sysconfig/network-scripts 配置网卡
- "SDOI2016" Journey Problem Solution
- The uniapp applet checks and prompts for updates
- Difference between first and take(1) operators in NgRx
- 信奥学习规划 信息学竞赛之路(2022.07.31)
- Keil nRF52832下载失败
- 博弈论(Depu)与孙子兵法(42/100)
- 面试突击69:TCP 可靠吗?为什么?
猜你喜欢

2022-07-31:给出一个有n个点,m条有向边的图, 你可以施展魔法,把有向边,变成无向边, 比如A到B的有向边,权重为7。施展魔法之后,A和B通过该边到达彼此的代价都是7。 求,允许施展一次魔法
![[1161. The maximum sum of elements in the layer]](/img/59/7810f425431779aa719458038ea0b3.png)
[1161. The maximum sum of elements in the layer]

程序进程和线程(线程的并发与并行)以及线程的基本创建和使用

Drawing process of hand-drawn map of scenic spots

面试突击69:TCP 可靠吗?为什么?

Binary tree non-recursive traversal

cobaltstrike

SVN服务器搭建+SVN客户端+TeamCity集成环境搭建+VS2019开发

Shell common script: Nexus batch upload local warehouse script

UOS统信系统 - WindTerm使用
随机推荐
Network security - crack WiFi through handshake packets (detailed tutorial)
【ACM】2022.7.31训练赛
[Reading Notes -> Data Analysis] 02 Data Analysis Preparation
程序进程和线程(线程的并发与并行)以及线程的基本创建和使用
/etc/sysconfig/network-scripts configure the network card
How to import a Golang external package and use it?
信奥学习规划 信息学竞赛之路(2022.07.31)
Flutter教程之 02 Flutter 桌面程序开发入门教程运行hello world (教程含源码)
Flutter教程之 01配置环境并运行demo程序 (教程含源码)
周总结
I don't know what to do with sync issues
cobaltstrike
输入输出优化
【云驻共创】【HCSD大咖直播】亲授大厂面试秘诀
Thinking and Implementation of Object Cache Service
SQL injection Less54 (limited number of SQL injection + union injection)
When can I use PushGateway
The uniapp applet checks and prompts for updates
vim的基本使用概念
Handwritten a simple web server (B/S architecture)