基类指针指向子类对象的原理解释——类的内部存储结构和内存分布及虚继承时的特殊情况

之前粗浅得了解了基类指针指向子类对象时,会舍弃子类所独有的那一部分。
直观地来看,这是通过解引用父类指针后,无法通过它来访问子类类成员变量,但可以通过虚函数表来调用子类重写的虚函数。这一部分可以搜很多文章来看,基本很清晰。如
C++ 虚函数表、函数地址、内存布局解析讲的很不错

2020.8.6发现一篇也写得很不错,很全面的文章
C++类内存分布

再者还有一篇 C++类的内存分布也利用 /d1 reportSingleClassLayoutXXX 这个命令行来直接查看类的内存分布,并且一并可以看懂结构体内存对齐。

先把一个前置结论放在这:存在继承关系时,父类成员变量放在前面,子类成员变量在后面。虚继承时,父类成员放在普通继承和子类成员**后面**。且,即便是虚继承时,仍然可以通过基类指针指向子类对象的方式,调用父类成员。

**那么存在虚继承时,基类指针指向子类对象,既然父类成员成员放在最后,是怎样通过父类指针访问他们的呢?**不多说,上代码
在这里插入图片描述
在这里插入图片描述

呀,原来是用到了vbptr虚基类指针!而且他被放在了最前面!所以我们看到派生类的大小为16,每个指针都是4,$vbtable@是指虚基类表,可以看到它记录了虚基类在子类内存分布中的的偏移地址,通过这个偏移再从指针起始位置寻找该父类成员!由此可以通过上述方式来访问基类成员!
再通过混合一个普通继承来加深理解存储顺序,现在在原来的基础上加一个public Base2的父类
在这里插入图片描述
在这里插入图片描述
普通继承的那一部分放在前面,虚继承的在后面,而且我们知道,每一次继承,都会继承父类的虚函数表指针并替换部分虚函数表中的函数,可以看到,虚继承时是一并将虚函数表指针看作父类一部分而将其挪到最后了。而虚基类指针是属于派生类的,所以虚基类指针在这种混合继承的情况下还是得靠后站。
另外在这个例子里,存在二义性问题,也就是base1和base2都有basebase这个成员变量,但这可不是别的文章里写的菱形继承二义性问题哦!是无法通过虚继承来解决的。如果不去访问basebase,是可以编译通过的,但一旦访问,就会出错哦
在这里插入图片描述
虚继承是为了解决菱形继承问题的,常见的例子:iostream其实是istream和ostream的派生类,而istream和ostream其实都派生自同一个基类ios

iostream类的基类有两个,分别是basic_istream和basic_ostream,而这两个类又都是basic_ios类的派生类.

这其实就是虚继承的一个具体应用。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值