C++ 虚继承

本文介绍了C++中的虚继承机制,用于解决多继承可能导致的同一基类数据成员被多次包含的问题。通过虚基类,确保所有子类只拥有基类的一份数据。详细阐述了虚继承的实现原理,包括虚基类表指针(vbptr)和虚表(virtual table),并展示了虚继承前后类的内存分布变化。

在 C++ 多继承中,可能会出现 the most derived class 拥有多个 the most based class 的多份相同数据成员。比如说下面这种菱形继承的情况:

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;
};

在这里插入图片描述
我们可以用 VS 提供的开发人员命令提示工具来显示 D 类型对象的内存布局如下:
在这里插入图片描述

  • D 对象中包含 B 对象和 C 对象,其中 B 对象和 C 对象又分别包含 A 对象,所以每一个 D 对象包含了两份 A 对象的数据,所以最终每一个 D 对象包含了:B::a, b, C::a, c, d,也就是 5 个 int 值,sizeof(D) = 5 * 4 = 20
  • 侧边的数据表示该数据在对象中的内存分布的偏移量

打开 vs 开发人员命令提示符后,首先定位到类所在的文件夹,然后输入:cl [类所在文件名称.cpp] /d1 reportSingleClassLayout[需要显示内存分布的类的名称]。
以显示上面 D class 为例,先 cd 到类所在文件夹,然后输入:cl NormalInheritance.cpp /d1 reportSingleClassLayoutD
回车即可


为了解决以上的在多继承中可能出现的继承多份基类数据成员的问题,C++ 采用的是一种虚继承的方式,指定某一个类为虚基类(virtual base class),然后其直接子类虚继承这个虚基类,那么其所有的子类,无论是直接子类还是间接子类,都只拥有一份虚基类的数据成员:

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;
};
  • class A 就是虚基类,class B 和 class C 是它的直接子类,class D 是它的间接子类

我们可以对比前后各个类的内存分布情况:
在这里插入图片描述

  • 继承虚基类的直接子类都会有一个虚基类表指针(virtual base table pointer, vbptr),指向一个虚表(virtual table),虚表中记录着虚基类数据相对于本类的偏移。比如说,对于 class B, class C,它们的虚表如下:
    在这里插入图片描述
  • class B 中 virtual base A 数据的偏移量为 8,从 B 的内存分布可以验证
  • class C 中 virtual base A 数据的偏移量为 8,同理,从 C 的内存分布可以验证
  • class D 中就包含 class B 的 vbptr,b, class C 的 vbptr, c, 以及一份 class A 的数据。这两个 vbptr 分别指向两个 vitual table:
    在这里插入图片描述
  • class D 中的 class B 成分中的 class A 数据的偏移量为 20;class D 中的 class C 成分中的 class A 数据的偏移量为 12 (20 - 8)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值