这是关于一个普通双非本科大一学生的C++的学习记录贴
在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料
那么开启正题
今天分享的是关于继承的知识点
1.菱形继承
我们有许多关于继承的方式
1.单继承
一个子类只有一个直接父类称这个继承关系为单继承
class A
{
public:int _a;
};class B : public A
{
public:int _b;
};class C : public B
{
public:int _c;
};
2.多继承
一个子类有两个或以上直接父类时称这个继承关系为多继承
class A
{
public:int _a;
};class B
{
public:int _b;
};class C : public A, public B
{
public:int _c;
};
3.菱形继承
菱形继承是多继承的一种特殊情况
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;
};
菱形继承的问题:菱形继承有数据冗余和二义性的问题,如上面的D对象中会出现两份_a成员
2.菱形虚拟继承
引出了菱形继承的问题,我们必然有解决的办法,下面介绍办法及菱形虚拟继承
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;
};
上面就是一种最简单的菱形虚拟继承的模型
虚拟继承可以解决菱形继承的二义性和数据冗余的问题,如上面的继承关系,在B,C继承A的时候使用虚拟继承即可,需要注意的是,虚拟继承不要在其他的地方去使用
3.虚拟继承解决数据冗余和二义性的原理
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;
};
我们再次借助这个模型来了解虚拟继承的原理
在vs环境下进入调试,内存窗口中我们可以发现,_a在对象内存的最下面,属于B,C公共的成员,
那么如果我们将D切割给B(C),此时B(C)如何找到A呢?
这里是通过了B和C内的两个指针,指向的一张表,这两个指针叫做虚基表指针,虚基表中存的是偏移量,通过偏移量可以找到下面的A
4.继承的总结与反思
1.C++语法复杂,多继承就是一个体现,有了多继承,就存在菱形继承,因而有菱形虚拟继承,底层实现就很复杂
2.多继承可以认为是C++的一种缺陷,Java就没有多继承
3.继承和组合
继承是一种is_a的关系,也就是说每一个派生类对象都是一个基类对象
组合是一种has_a的关系,假如B组合了A,每个B对象中都有一个A对象
实际中,优先使用对象组合,而不是类继承(组合的耦合度低,代码维护好)
当然有些情况更适用于使用继承,那么使用继承也无可厚非
新手写博客,有不对的位置希望大佬们能够指出,也谢谢大家能看到这里,让我们一起学习进步吧!