浅然的专栏

开源梦想家

C++(笔记)浅析菱形继承&虚继承底层内存占用

一、什么是菱形继承

这里写图片描述

二、代码实现

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h>
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;

class A
{
public:
    void run()
    {
        cout<<"A running"<<endl;
    }
private:
    int a;
};
class B:public A
{
private:
    int b;
};
class C:public A
{
private:
    int c;
};
class D:public B,public C
{
private:
    int d;
};

int main()
{
    D d;
    d.run();
    return 0;
}

以上代码编译的时候是报错的,报错结果为run函数是不确定的

这里写图片描述

导致run不确定的原因是:D的对象模型里面保存了两份A,当我们想要调用A里继承的run时就会调用不明确,并造成数据冗余问题(明明只要一份就好,我们却保存了两份)


解决方法

1.使用作用域(不建议)

只需在主函数中改变

int main()
{
    D d;
    d.B::run();
    d.C::run();
    return 0;
}

2.使用虚继承(建议)

虚继承即让B和C在继承A时加上virtual关键字,记住不是D虚继承

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h>
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;

class A
{
public:
    void run()
    {
        cout<<"A running"<<endl;
    }
private:
    int a;
};
class B:virtual public A
{
private:
    int b;
};
class C:virtual public A
{
private:
    int c;
};
class D:public B,public C
{
private:
    int d;
};

int main()
{
    D d;
    d.run();
    return 0;
}

三、解析虚继承原理

TDM-GCC 4.9.2 64-bit Release下编译(不同环境下所占大小不同)

1、普通继承下占用内存(字节)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h>
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;

class A
{
public:
    void run()
    {
        cout<<"A running"<<endl;
    }
private:
    int a;
};
class B:public A
{
private:
    int b; 
};
class C:public A
{
private:
    int c;
};
class D:public B,public C
{
private:
    int d;
};

int main()
{
    cout<<"A="<<sizeof(A)<<endl;//A=4
    cout<<"B="<<sizeof(B)<<endl;//B=8
    cout<<"C="<<sizeof(C)<<endl;//C=8
    cout<<"D="<<sizeof(D)<<endl;//D=20
    return 0;
}

如果A没有int a那么A占1个字节(这一个字节是A类本身所占用的)


2、虚继承下占用内存

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h>
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;

class A
{
public:
    void run()
    {
        cout<<"A running"<<endl;
    }
private:
    int a;
};
class B:virtual public A
{
private:
    int b; 
};
class C:virtual public A
{
private:
    int c;
};
class D:public B,public C
{
private:
    int d;
};

int main()
{
    cout<<"A="<<sizeof(A)<<endl;//A=4
    cout<<"B="<<sizeof(B)<<endl;//B=16
    cout<<"C="<<sizeof(C)<<endl;//C=16
    cout<<"D="<<sizeof(D)<<endl;//D=40
    return 0;
}

B和C从8字节变成了16字节,是因为包含了一个指向虚表指针占8字节
而D从20字节变成了40字节,是包括A(4),B/C(16),本身(4)

阅读更多

扫码向博主提问

去开通我的Chat快问

w_linux

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • Java
  • MySQL
版权声明:本文为博主原创文章,转载请注明出处 浅然的专栏 https://blog.csdn.net/w_linux/article/details/71158082
个人分类: 【C/C++】
所属专栏: C++阅读笔记
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭