虚拟继承与菱形虚拟继承
来源:互联网 发布:大数据建设 一流公司 编辑:程序博客网 时间:2024/05/07 03:29
虚拟继承
什么是虚拟继承?
虚拟继承是C++编程语言中的一种语法,使得派生类如果继承基类多次,只有一份基类的拷贝在派生类对象中。需在在继承方式前加上virtual。
#include<iostream>using namespace std;class B{public: int _b;};class D:virtual public B{public: int _d;};int main(){ D d; d._b = 1; d._d = 2; return 0;}
这是一个简单的单虚拟继承。相关赋值后我们去内存看看派生类对象的模型。
我们看到第二行存放的是_d的值,最后一行存放的是_b的值。那么第一行这一串数据是什么呢?这其实是一个地址(偏移量表的地址),我们去这个地址看看里面存放了些什么。
这其中第一行的0代表着偏移量表相对于自己的偏移量,为0。第二行的8代表着偏移量表相对于基类的偏移量,为8。
单虚拟继承派生类的空间模型
我们去看看反汇编代码
我们发现在调用D构造函数之前有push 1这样的代码,这其实是虚拟继承的标志。
派生类D的构造函数到底做了什么,要访问基类成员应该怎么访问?
偏移量表的地址由派生类D的构造函数填写,要想访问基类成员,首先要去找偏移量表,之后根据与基类的偏移量进行访问。
菱形虚拟继承
回想菱形继承,一个派生类D继承了基类C1,C2。C1与C2同时继承了相同的基类B。当我们直接由派生类对象d对基类B的成员进行操作时,会出现二义性的问题。因为编译器不知道你所说的基类B是C1所继承的还是C2所继承的。
虚拟继承完美的解决了这个问题。 派生类D如果继承了多次基类,只有一份基类的拷贝在派生类内。
问题来了,虚拟继承应该发生在那个地方?
这个问题很简单,如果发生在派生类D多继承C1,C2时,C1,C2已经同时继承了基类B,届时派生类D中已经存在了两份基类B的拷贝。因此虚拟继承应该发生在C1,C2继承基类B时。
#include<iostream>using namespace std;class B{public: int _b;};class C1:virtual public B{public: int _c1;};class C2:virtual public B{public: int _c2;};class D:public C1,public C2{public: int _d;};int main(){ D d; d._b = 1; d._c1 = 2; d._c2 = 3; d._d = 4; return 0;}
同样我们看看派生类d在内存中的模型。
首先我们看到第二行存放_c1的值,第四行存放_c2的值,接着就是_d,在最底部存放_b。同样这其中存放了两个偏移量表的地址。我们去分别看看两张偏移量表有什么不同。
先去0x0129580c看看
同样第一行是偏移量表相对自己的偏移量为0。第二行是偏移量表相对基类B的偏移量为14(十六进制,十进制为20)。
之后去0x01295800看看
第一行是偏移量表相对自己的偏移量为0。第二行是偏移量表相对基类B的偏移量为0c(十六进制,十进制为12)。
我们可以得出派生类对象d的模型
我们可以看到派生类对象内部只存放了一份基类拷贝,这时对基类成员_b进行赋值时不会出现二义性问题。
- 继承*菱形继承与菱形虚拟继承
- 菱形继承与虚拟继承
- 菱形继承与虚拟继承
- 虚拟继承与菱形虚拟继承
- 菱形继承与菱形虚拟继承
- 菱形继承与菱形虚拟继承
- 菱形继承&菱形虚拟继承
- 菱形继承&菱形虚拟继承
- 菱形继承--菱形虚拟继承
- 菱形虚拟继承
- 菱形的虚拟继承
- 浅谈菱形虚拟继承
- 菱形虚拟继承
- 菱形虚拟继承
- 菱形虚拟继承详解
- 菱形虚拟继承
- 虚拟菱形继承
- 【C++】菱形继承与虚拟菱形继承的对比分析
- 实现app之间的跳转
- cocos2d-x C++部分编译出现 error C1083 无法打开源文件,No such file or directory
- 发现了一个有趣的字体:Fira Code字体(Eclipse可用)
- centos7 安装rmp mysql 5.7过程
- Android进阶之路
- 虚拟继承与菱形虚拟继承
- C语言在单片机开发中的一些技巧
- EFR32MG项目开发“复盘”
- 目标检测与跟踪
- 微信小程序开发(6)-表单数据组件的使用(picker,form,input,button)
- 数学黑洞
- 经典算法之快速排序
- Docker常用命令总结
- 关于AfxMessageBox没有重载函数