c++继承(单继承,多继承,菱形继承和虚继承)详解

原创 2017年07月21日 14:36:32

下面我将从继承实例(代码 )继承对象模型原理来分析继承。
单继承
模型
这里写图片描述
代码

class A
{
public:
    int _a;
};
class B:public A
{
public:
    int _b;
};
int main()
{
    B b;
    b._a = 0;
    b._b = 1;

    return 0;
}

代码分析:
这里写图片描述
多继承
模型
这里写图片描述

class A
{
public:
    int _a;
};
class B
{
public:
    int _b;
};
class C :public A, public B
{
public:
    int _c;
};
int main()
{
    C c;
    c._a = 0;
    c._b = 1;
    c._c = 2;

    return 0;
}

代码分析
这里写图片描述
多继承我们要注意一个问题:当继承列表发送变化时,那么我们的对象模型也将发生改变。
原则:继承列表先写谁,谁将在低地址。和谁的类在不在前面无关,只于几次列表有关
我将 class C :public A, public B换成class C :public B, public A那么c的对象模型将变成下面的格式
这里写图片描述
菱形继承
模型
这里写图片描述

class A
{
public:
    int _a;
};
class B:public A
{
public:
    int _b;
};
class C:public A
{
public:
    int _c;
};
class D:public B,public C
{
public:
    int _d;
};

int main()
{
    D d1;
    d1._a = 0;
    d1._b = 1;
    d1._c = 2;
    d1._d = 4;


    return 0;
}

代码将不能编译通过,提示
这里写图片描述
当屏蔽//d1._a = 0;后可以通过编译,但是我们将无法访问父类的成员。所以我们迫切需要解决它的办法。
我们仔细看看报的错误,访问对象不明确,于是我们可以通过下面的方法进行访问_a:

d1.B::_a = 3;
d1.C::_a = 0;

这样就可以通过编译了。
下面我们研究下它的对象模型
这里写图片描述
我们通过计算可以得到对象d1的大小为20字节。但是对于我们来说,查找基类的成员变得困难了,有没有一种方式来解决这个问题?
于是虚继承出现了,它解决了菱形继承访问父类成员出现的二义性问题
下面我们一起来看看它是怎么解决二义性问题的:
虚继承
虚继承就是在被继承的前面加上virtual关键字
它是菱形继承的一种改进,所以它的继承方式和菱形继承一样,只是对象模型有区别。

class A
{
public:
    int _a;
};
class B:virtual public A
{
public:
    int _b;
};
class C :virtual public A
{
public:
    int _c;
};
class D:public B,public C
{
public:
    int _d;
};

int main()
{
    D d1;
    cout << sizeof(d1) << endl;
    d1._a = 0;
    d1._b = 1;
    d1._c = 2;
    d1._d = 4;


    return 0;
}

这里写图片描述
加入虚继承后d1的大小变成24字节,因为C类和B类都多了一个相对于_a的偏移量,所以多了四个字节。虚继承只有一份父类的数据,但是他在别的类中增加了四个字节来获取基类成员相对于别的类的偏移量。这样就解决了在菱形继承的二义性问题,但是它也引入了,程序性能下降的问题,这里就不做详细的说明。

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

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

C++中的多态、单继承、多继承、菱形继承、菱形虚拟继承

C++中的继承体系,有单继承、多继承、菱形继承、菱形虚拟继承,以及各类型的对象模型,我们今天做一个简单的剖析 (1)什么多态? 所谓多态,就是“多种形态”。在面向对象的方法中一般是这样描述多态的:...
  • lyl194458
  • lyl194458
  • 2017年08月02日 22:06
  • 169

多继承(非虚继承)派生类对象内存结构(基类有虚函数)

在多继承中(非虚继承),探索一下派生类对象在内存中怎么分布的。
  • KangRoger
  • KangRoger
  • 2014年08月01日 08:18
  • 1918

C++之单继承与多继承

继承性是面对对象程序设计中最重要的特征之一它允许在既有类的基础上创建新类,并可以根据所面对问题的不同情况对新类进行更具体,更详细的说明与操作。 通过代码看基类与派生类class A /...
  • qq_36782456
  • qq_36782456
  • 2017年04月13日 16:37
  • 1203

C++菱形继承与虚继承

虚继承,菱形继承
  • xiaolewennofollow
  • xiaolewennofollow
  • 2016年08月14日 12:20
  • 804

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

虚函数所谓虚函数,从其功能上来看是采用虚调用的方式;当子类重新定义其父类的虚函数以后,父类指针根据付给他的不同子类指针,动态地调用属于子类的该函数;假如一个类有虚函数,则该类会因为维护该虚函数,而额外...
  • misol
  • misol
  • 2011年07月13日 21:07
  • 3183

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

菱形继承是多重继承中跑不掉的,Java拿掉了多重继承,辅之于接口。C++中虽然没有明确说明接口这种东西,但是只有纯虚函数的类可以看作Java中的接口。在多重继承中建议使用“接口”,来避免多重继承中可能...
  • jackyvincefu
  • jackyvincefu
  • 2014年01月05日 09:05
  • 10520

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

(1)C++继承概念: C++继承分为公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。在C++语言中,一个派生类可以从一个基类派生,也可以从多...
  • yx20130919
  • yx20130919
  • 2016年06月17日 12:17
  • 468

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

虚继承和虚函数是完全无相关的两个概念。 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝。这将存在两个问题:其一,浪费存储空间;第二,存在二义性问题,通常可...
  • bxw1992
  • bxw1992
  • 2017年08月30日 22:26
  • 1397

继承*菱形继承与菱形虚拟继承(上)

面向对象程序设计的核心思想是封装(数据抽象)、继承和多态(动态绑定)。 通过使用数据抽象,我们可以将类的接口与实现分离; 使用继承,可以定义相似的类型并对其相似关系建模; 使用动态绑定,可以在一...
  • qq_34992845
  • qq_34992845
  • 2017年02月27日 22:26
  • 935
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++继承(单继承,多继承,菱形继承和虚继承)详解
举报原因:
原因补充:

(最多只允许输入30个字)