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

来源:互联网 发布:大数据交易中心 编辑:程序博客网 时间:2024/06/05 14:40

一、什么是菱形继承

这里写图片描述

二、代码实现

#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)

1 0
原创粉丝点击