关闭

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

标签: C++菱形继承虚继承底层内存
524人阅读 评论(0) 收藏 举报
分类:

一、什么是菱形继承

这里写图片描述

二、代码实现

#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
查看评论

C++(虚)继承类的内存占用大小

首先,平时所声明的类只是一种类型定义,它本身是没有大小可言的。 因此,如果用sizeof运算符对一个类型名操作,那得到的是具有该类型实体的大小。 计算一个类对象的大小时的规律: 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同); 2、一个类中,虚函数本身、成员函数(包括...
  • l494926429
  • l494926429
  • 2016-07-19 17:21
  • 955

C++菱形继承与虚继承

虚继承,菱形继承
  • xiaolewennofollow
  • xiaolewennofollow
  • 2016-08-14 12:20
  • 804

C++继承和菱形继承中的虚继承

(1)C++继承概念: C++继承分为公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承,还有一种结构特殊的菱形继...
  • yx20130919
  • yx20130919
  • 2016-06-17 12:17
  • 471

【C++基础之二十一】菱形继承和虚继承

菱形继承是多重继承中跑不掉的,Java拿掉了多重继承,辅之于接口。C++中虽然没有明确说明接口这种东西,但是只有纯虚函数的类可以看作Java中的接口。在多重继承中建议使用“接口”,来避免多重继承中可能出现的各种问题。 1.菱形继承 先看一下菱形继承长什么样。 B和C从A中继承,而D多重继...
  • jackyvincefu
  • jackyvincefu
  • 2014-01-05 09:05
  • 10533

菱形继承和虚继承、对象模型和虚基表

菱形继承的对象模型、虚继承的对象模型、以及深入探究虚基表的内容,为什么虚基表存放对象的偏移量要存放在第二个位置,而不是第一个位置?
  • skyroben
  • skyroben
  • 2017-03-25 19:25
  • 968

【C++拾遗】 从内存布局看C++虚继承的实现原理

准备工作 1、VS2012使用命令行选项查看对象的内存布局 微软的Visual Studio提供给用户显示C++对象在内存中的布局的选项:/d1reportSingleClassLayout。使用方法很简单,直接在[工具(T)]选项下找到“Visual Studio命令提示(C)”后点击即可。切...
  • Xiejingfa
  • Xiejingfa
  • 2015-08-27 16:49
  • 2730

C++中虚继承的作用及底层实现原理

虚继承和虚函数是完全无相关的两个概念。 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝。这将存在两个问题:其一,浪费存储空间;第二,存在二义性问题,通常可以将派生类对象的地址赋值给基类对象,实现的具体方式是,将基类指针指向继承类(继承类有基类的拷贝)中的...
  • bxw1992
  • bxw1992
  • 2017-08-30 22:26
  • 1439

C++ 虚函数 单一继承 多重继承 单一虚继承 菱形虚继承 的简洁总结

虚函数所谓虚函数,从其功能上来看是采用虚调用的方式;当子类重新定义其父类的虚函数以后,父类指针根据付给他的不同子类指针,动态地调用属于子类的该函数;假如一个类有虚函数,则该类会因为维护该虚函数,而额外产生一个指针vptr,该指针指向一个虚表,虚表中保存了该类所有的虚函数地址;说到
  • misol
  • misol
  • 2011-07-13 21:07
  • 3185

【C++】c++单继承、多继承、菱形继承内存布局(虚函数表结构)

c++单继承、多继承、菱形继承内存布局(虚函数表结构)
  • SuLiJuan66
  • SuLiJuan66
  • 2015-10-04 18:44
  • 2970

带有虚函数的菱形继承和带有虚函数的菱形虚继承

对于某些函数来说,基类希望它的派生类定义适合自身的版本,此时基类就将这些函数声明为虚函数。 在存在虚函的类,创建对象时会产生虚表指针,虚表指针指向一个虚表,这时就可以通过虚表访问自己定义的函数。 通过下面两种继承进行分析: 【带有虚函数的菱形继承】 以下图的模型为例进行分析: cl...
  • D_leo
  • D_leo
  • 2017-04-12 19:10
  • 578
    个人资料
    • 访问:135037次
    • 积分:3845
    • 等级:
    • 排名:第9857名
    • 原创:222篇
    • 转载:1篇
    • 译文:0篇
    • 评论:85条
    和我一起学习
    访客记录
    博客专栏