C++普通继承、多继承、虚继承内存空间排布分析

一、普通继承

  1. 代码
class A
{
public:
	virtual void virtualfunA(){
	}
	virtual void virtualfunAA(){
	}
	void funA(){
	}
public:
	int a;
};

class B : public A
{

public:
	virtual void virtualfunA(){
	}
	virtual void virtualfunB(){
	}
	void funB(){
	}
public:
	int b;
};

int main(){
	A obj1;
	B obj2;
	return 0;
}
  1. 内存结构
    在这里插入图片描述
    在这里插入图片描述

看到我发现了一个有趣的地方,就是B类中的虚函数virtualfunB出现在obj2的虚表中。

  1. 总结
    普通继承中,子类重写父类的虚函数后会在虚表中覆盖父类的虚函数,子类增加特有的虚函数, 要在第一个虚表中添加.

二、多继承

  1. 代码
class A1
{
public:
	virtual void funA1(){}
	virtual void funA11(){}
public:
	int a1;
};

class A2
{
public:
	virtual void funA2(){}
	virtual void funA22(){}
public:
	int a2;
};

class B : public A1 ,public A2
{
public:
	virtual void funA1(){}
	virtual void funA2(){}
	virtual void funB(){}
public:
	int b;
};
int main()
{
	B obj;
	return 0;
}
  1. 内存结构
    在这里插入图片描述

总结:多继承的内存空间顺序是按照继承顺序排布的。

三、菱形继承

描述:上面的多继承中有一个经典的菱形继承问题,如果多继承的对象中存在某两个类继承同一个基类,那么会出现数据冗余现象,这会导致数据不一致。

如图:在这里插入图片描述
这种情况C对象中会出现两个a变量

  1. 代码
#include<iostream>
using namespace std;

class A
{
public:
	int a;
};

class B1 : public A
{
public:
	int b1;
};

class B2 : public A
{

public:
	int b2;
};

class C : public B1,public B2
{
public:
	int c;
};

int main()
{
	C obj;
	
	return 0;
}
  1. 内存结构
    在这里插入图片描述
    总结:这种情况我么可以用虚继承来解决这类问题

四、虚继承

虚继承特性:

  1. 父类和子类在空间上倒置关系(与普通继承比较)
  2. 虚继承, 子类会复制父类的虚表, 此外, 自己特有虚函数, 自己会有虚表, 自己也会有对应的虚指针. 2个虚指针, 一个指向父类复制过来的虚表,一个指向自己的虚表
  3. 子类存在指向虚基类(虚继承里面的基类) 的虚基表 , 子类会有指向虚基表的指针 vbptr , 虚基表里面内容是指向自己和虚基类的偏移量
  4. 最底层的子类, 完成虚基类的构造.

1.部分虚继承

  1. 代码
class A
{
public:
	virtual void funA(){}
public:
	int a;
};

class B1 : virtual public A
{
public:
	virtual void funB1(){}
public:
	int b1;
};

class B2 : virtual public A
{
public:
	virtual void funB2(){}
public:
	int b2;
};

class C : public B1,public B2
{
public:
	virtual void funC(){}
public:
	int c;
};

int main()
{
	C obj;
	return 0;
}

2.内存结构
在这里插入图片描述
vbptr的作用是找到自己的虚表和自己继承类的虚表

2.完全虚继承

  1. 代码
class A
{
public:
	virtual void funA(){}
public:
	int a;
};

class B1 : virtual public A
{
public:
	virtual void funB1(){}
public:
	int b1;
};

class B2 : virtual public A
{
public:
	virtual void funB2(){}
public:
	int b2;
};

class C : virtual public B1,public B2
{
public:
	virtual void funC(){}
public:
	int c;
};

int main()
{
	C obj;
	return 0;
}
  1. 内存结构
    在这里插入图片描述
    vbptr的作用是找到自己的虚表和自己继承类的虚表

总结

由内存结构可知,这两种方法都是可以解决菱形继承问题的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长不大的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值