类的内存模型(二)
发布日期:2021-07-27 05:04:45 浏览次数:5 分类:技术文章

本文共 1445 字,大约阅读时间需要 4 分钟。

类的内存模型(二)

1. 单继承关系的对象模型

单继承代码如下:

class Base{	private:		int m_Ba;		int m_Bb;	public:		virtual void test();};class Derived : public Base {	private:		int m_Da;	public:		virtual void test();		virtual void print();};

对于基类,和之前简单的对象不一样,该对象的内存空间不仅存储非静态的成员变量,而且存储了一个指针,叫“虚指针(vptr)”。只要有虚函数,对象的内存空间就会多出一个虚指针。但注意:无论该对象有多少个虚函数,对象的内存空间也最多只有一个虚指针。虚指针指向虚表,虚表的每个元素不是函数而是函数指针。

下面是子类的对象的构造过程,即 执行Derived d

  1. 子类继承父类,所以按照父类构造方式构造(只是按照父类方式,但是还是属于子类对象的内存空间);

  2. 按照父类方式构造完,新增子类独有的成员变量;

  3. 新增虚函数(当虚函数与父类虚函数重复时,覆盖虚表中对应的项,即替换函数指针);

  4. 当子类需要新增虚函数时,需要在虚表中新增一项,存储新的虚函数的函数指针。

    以上就是单继承派生类下的内存分布,下面在VS中查看基类Base的内存分布:

    image-20201122213830994

然后,再看下单继承类Derived的内存模型:

image-20201122214033990

总结:派生类在继承父类的基本构造方法基础上,也会存储自身的成员变量,继承父类的虚表并在此基础上进行修改。子类的虚函数与父类的虚函数重复时,就讲子类的虚函数指针覆盖到虚表中对应项,对于子类的新的虚函数,会在虚表上新建一项。

2. 多继承下的内存模型

多继承:一个子类有多个父类。

代码如下:

class BaseA{	public:		virtual void testA();	private:		int m_BA;};class BaseB{	public:		virtual void testB();	private:		int m_BB;};class Derived : public BaseA, public BaseB {	public:		virtual void testA();		virtual void testB();		virtual void testD();	private:		int m_D;};

转化成UML图之后,如下:

子类内存模型构造如图:

使用VS查看,如下图:

image-20201122220714543

考虑一个问题:菱形继承。用UML表示如下:

使用VS查看内存模型:

image-20201122221547816

问题:Derived的内存空间中有两份m_B,浪费内存空间;其二就是使用时会有歧义。

原因:因为BaseA、BaseB都是继承于Base,所以BaseA、BaseB各有一份m_B,而Derived又是继承于BaseA、BaseB,自然Derived的布局要按照BaseA、BaseB的方式来分布,所以,Derived有两份m_B。

方法1:可以通过指定访问对象来解决

Derived dd;dd.BaseA::m_B = 1;dd.BaseB::m_B = 2;

方法2:要解决空间浪费的问题,就只能使用虛继承来解决。

https://mp.weixin.qq.com/s/pV7lWM5lIKio9b16AW3Rxg

https://mp.weixin.qq.com/s/81vskUmNXYAx6x3FIjl4vA

转载地址:https://blog.csdn.net/qq_45434780/article/details/109967079 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:生产者消费者模型
下一篇:类的内存模型(一)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年09月17日 02时17分03秒