C++多继承,虚继承,虚基类,内存剖析

文章讲述了C++中多继承导致的菱形继承问题,如数据冗余和二义性,以及C++通过引入虚继承来优化内存布局,消除这些问题。虚基类通过共享基类数据和存储偏移量解决了继承效率和一致性问题。
摘要由CSDN通过智能技术生成

C++作为最早进入面向对象的语言,是面向对象的先驱者,为面向对象做了很多尝试,多继承就是其中之一,事实上多继承会导致一些问题,比如菱形继承的数据冗余,二义性,菱形继承,即下图

D继承B,C后会有三份A中数据,此时就造成了数据的冗余,因为D很有可能压根不需要这么多A中数据,并且直接使用A中数据还会造成二义性,因为除非指明是哪个里的A数据,否则无法直接使用,为了解决这一问题,C++推出了虚继承,即在继承对象前加virtual关键字,首先我们先来看一下正常使用非虚继承D的内存布局,测试代码如下

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.A::_a = 1;
	d.B::_a = 2;
	d.C::_a = 3;
	d._b = 4;
	d._c = 5;
	d._d = 6;

	return 0;
}

内存布局如下

首先要说一点的是,D和B共用的是同一个_a,这也是早期C++对多继承的一个优化,使得数据明确,其他数据如内存分布所示,一个int四个字节,看起来十分正常

下面是使用虚继承的测试代码

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

	return 0;
}

下图是类刚创建好时的内存布局

我们发现对象创建后相比之前多了一些标红的东西,这是一个内存地址

下图是所有数据初始化赋值后的内存布局

可以看到的是除_a以外其他的数据上方都有额外的四个字节去存储了一个地址,这个地址所指向的是偏移量,是对多继承_a的偏移量,下面是三个地址里所存储的偏移量

他们分别是8,-4,-12的补码,也就是说虚继承的对象会在其他数据里多增加一份地址,地址存放的是对多继承对象的偏移量,这样就可以直接使用_a,解决二义性的问题,且所有继承的派生类都使用这一份_a数据,解决了数据冗余的问题,这样继承下来的类,就叫做虚基类

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值