【C++】菱形继承

news/2024/7/8 7:16:09

我们先来看下菱形继承的基本视图以及基本的代码结构

下面来看下简单的代码以及数据结构:

class Person
{
public:int a_p;
};class Studen :public Person
{
public:int a_st;
};class Stuff :public Person
{
public:int a_sf;
};class st_sf :public Stuff, public Studen
{
public:int a_ss;
};int main()
{st_sf ss;return 0;
}

上述代码简单的很,就是Student(学生)和stuff(工人)都继承了Person类,然后Student和stuff作为Person的派生类,但是他俩又作为了类st_sf 的两基类,在主函数中创建类st_sf 的对象,下面我们来看下创建的st_sf 对象的数据结构是咋样的?

 

 上图中说到的会导致一些问题,具体是什么问题呢,看下面代码:

#include<iostream>
using namespace std;class A
{
public:int val;
public:A(int x = 0):val(x){}
};class B : public A
{
public:int num;
public:B(int x = 0) : num(x), A(x + 10) {}
};class C : public A
{
public:int sum;
public:C(int x = 10) :sum(x), A(x + 10) {}
};class D :public B, public C
{
public:int total;
public:D(int x = 10) :total(x), B(x + 10), C(x + 20) {}
};int main()
{D d(0);return 0;
}

在上述代码中我们通过最底层基类A派生出来了B和C,然后B和C又共同派生出来了一个类D,通过实例化D对象来观察上述代码的数据结构视图:

 

我们可以清晰的看到,构建出来的D对象有歧义了B中的val值为20,C中的val值为30,很明显不符合正常情况,但是呢代码还是正常通过了,这是为什么呢??

 

上图中我们给出了产生这种现象的原因,就是因为上述现象,所以 才会有我们刚刚看到的歧义性,那么怎么解决这种问题呢???

我们在这里就给出来了一个解决方法:虚继承 

 

 虚继承会导致我们student和staff对象中存放与Person对象的指针偏移量,但是存放的不是指针,这样就可以避免我们的歧义性问题:

class A
{
public:int val;
public:A(int x = 0):val(x){}
};class B :virtual public A
{
public:int num;
public:B(int x = 0) : num(x), A(x + 10) {}
};class C :virtual public A
{
public:int sum;
public:C(int x = 10) :sum(x), A(x + 10) {}
};class D :public B, public C
{
public:int total;
public:D(int x = 10) :total(x), B(x + 10), C(x + 20), A(x + 100) {}
};int main()
{D d(0);return 0;
}

我们看一下引入虚继承之后的代码运行是怎么样的:

 

 该结果和我们上述画的哪个图结构一样,而且也没有歧义性的结果出现!!!

最后再补充一点东西,不使用虚继承的菱形继承不光会有歧义性结果:

//在没有引入虚继承之前,我们不可以这样调用:
int main()
{D d(0);d.val;//这样不可以调用,因为它的d对象的基类中有两个A中的成员变量,编译器不知道调用哪个//所以编译不通过
}

会有val不明确的报错!!! 

“趁着还有时间,加油学习!!!”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pgtn.cn/news/15578.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

ie旋转滤镜Matrix

旋转一个元素算是一个比较常见的需求了吧&#xff0c;在支持CSS3的浏览器中可以使用transform很容易地实现&#xff0c;这里有介绍&#xff1a;http://www.css88.com/archives/2168&#xff0c;这里有演示http://www.css88.com/tool/css3Preview/Transform.html&#xff0c;就不…

【C++】四种类型的转换

C四种类型的转换 包括这四种&#xff1a;const_cast , static_cast , dynamic_cast , reinterpret_cast 先来说下C语言中的类型转换&#xff0c;非常的暴力&#xff0c;就是耍流氓&#xff1a; float a 12.23; int b (int)a; 下面我写的都是最基础的&#xff0c;简单的&am…

【C++】满二叉树、完全二叉树等概念解释

二叉树中的判断有以下几种&#xff1a; 是否完全二叉树、是否满二叉树、是否为BST树、是否为平衡二叉树、是否为对称二叉树、完美二叉树 满二叉树&#xff1a; 除最后一层无任何子节点外&#xff0c;每一层上的所有结点都有两个子结点的二叉树。 上述所示图除最外一层节点之外…

【C++】多线程(链式、循环队列)实现生产者消费者模式

生产者消费者模式&#xff1a; 生产者消费者问题&#xff08;英语&#xff1a;Producer-consumer problem&#xff09;&#xff0c;也称有限缓冲问题&#xff08;英语&#xff1a;Bounded-buffer problem&#xff09;&#xff0c;是一个多线程同步问题的经典案例。该问题描述了…

添加引用方式抛出和捕获干净的WebService异常

转载&#xff1a;http://www.cnblogs.com/ahdung/p/3953431.html 说明&#xff1a;【干净】指的是客户端在捕获WebService&#xff08;下称WS&#xff09;抛出的异常时&#xff0c;得到的ex.Message就是WS方法中抛出的异常消息&#xff0c;不含任何“杂质”。 前提&#xff1a;…

基数排序(桶排序)

基数排序又叫桶排序&#xff1a; 先按照个位数排序&#xff0c;第一次排序好之后&#xff1b;再次按照十位数进行排序&#xff0c;第二次排序好之后&#xff1b;第三次对百位进行排序.................. 实现原理图&#xff1a;拿出一些个类似“桶”的东西 将分别按照个位&am…

如何用两个栈实现一个队列?

先看分析 来看代码&#xff0c;因为代码量巨大&#xff0c;其中包括两个头文件&#xff0c;两个实现函数 &#xff0c; 这块就写一个两个栈实现按一个队列的头文件以及函数名&#xff0c;填补代码不难的&#xff0c;有需要的话&#xff0c;我在评论区发出来&#xff1a; 这部分…

堆排序(超详细的原理图以及代码注释)

在了解学习堆排序之前&#xff0c;我们必须清楚以下的概念&#xff1a; 上述概念搞清楚之后&#xff0c;来看下面的原理图&#xff1a; 然后原理部分就讲完了 下面来看如何由子节点下标推出父节点和父节点下标推出子节点下标 下面这个原理图来展现一下为什么在调整大顶堆的时候…