c++中的继承关系分为单继承和多继承
单继承:一个派生类只有一个基类
多继承:一个派生类不止有一个基类
在多继承的过程成容易造成二义性问题。
菱形继承是多继承中的一种复杂的情况。
菱形继承的有两个问题:
二义性:当使用A的数据时无法确定继承自B 还是 C
数据冗余:类D中会有两份类A的数据
先看一个菱形继承的例子
#include
using namespace std;
class A{
public:
int _a = 1;
};
class B : public A{
public:
int _b = 2;
};
class C : public A{
public:
int _c = 3;
};
class D : public B,public C {
public:
int _d = 4;
};
int main(){
D d1;
//d1._a = 100;
d1.B::_a = 100; //可以显示的指定访问那一个类中的成员,解决了二义性问题
d1.C::_a = 101;
}
D中最后会出现两份_a,这就造成了数据冗余,为了解决数据冗余的问题,使用了虚拟继承
l菱形虚拟继承
通过菱形的虚拟继承,可以使该多继承体系中只有一份公共的A中的数据
//虚拟继承通过virtual关键字实现
class A{
public:
int _a = 1;
};
class B : virtual public A{
public:
int _b = 2;
};
class C : virtual public A{
public:
int _c = 3;
};
class D : public B,public C {
public:
int _d = 4;
};
在虚拟继承中通过使用虚基表,来实现虚拟继承不对原继承体系的原本继承关系造成影响。尽管现在只有一份公共的A,但原来的继承关系并不发生改变,只要继承了A都了能访问A的数据,我们通过它们的内存模型来看
通过虚基表我们可以发现,此时对象d1中只有一个A中的数据_a,不再出现冗余的两份_a,而原来存放继承自B中的_a的位置以及继承自C中的_a的位置,此时存放的是一个地址,找到该地址,发现其中存放的是数,而这个数就是一个偏移量,表示此时B和C的位置到达公共部分_a的偏移量。这两个地址叫做虚基表指针,而指向的就是虚基表,这两个虚基表中存放的是偏移量。
继承关系和组合关系
多继承体现了c++的语法复杂性,算是c++的一个设计缺陷,因为多继承的关系,所以有了菱形继承,从而出现了虚拟继承。从而导致了复杂度的上升,所以尽量少的使用多继承。
组合
class Legs{
protected:
size_t _size = 17; // 腿长
};
class Person{
protected:
string _name ;//姓名
Legs _leg;
};
继承体现的是设计层次结构中的复用,而还有一种对象间的服用关系,就是组合。
继承表明了每一个派生类对象都是一个基类对象,是一种has-a的关系。
组合关系表示,如果B组合A,表明每一个B对象中都有一个A对象,是一种is-a的关系。
-优先使用组合关系,而不是继承关系,表明了一个对象是组成另一个对象的一部分。
派生类与基类之间的关系又称为白箱复用,白箱是指可视性而言,在继承关系中基类内部的细节对于派生类来说是可见的,基类在一定程度上破坏了封装,基类的改变在很大程度上会影响派生类。所以继承关心间的关联性很强,耦合度很高。
组合关系是一种黑箱复用,被组合的类细节在另一个类中是不不可见的,被组合的类只需要提供良好的接口即可。组合之间的关系的依赖程度低,耦合度低,更能保证封装的完好性。
面向对象的设计中倾向于高内聚,低耦合的设计,所以继承和组合关系间,优先使用自合
总结以上是内存溢出为你收集整理的c++中的菱形继承与虚拟菱形继承全部内容,希望文章能够帮你解决c++中的菱形继承与虚拟菱形继承所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)