服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 一文读懂C++中的继承之菱形继承(案例分析)

一文读懂C++中的继承之菱形继承(案例分析)

2021-10-29 12:30九江董熙 C/C++

这篇文章主要介绍了C++中的继承之菱形继承的相关知识,通过案例给大家详细分析介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

前言

我们上一篇说了世间万物都有一个继承体制,或多或少子类继承了父类的某些特征,但大多都是单向继承,但是就有些特例他就是多继承,比如:

一文读懂C++中的继承之菱形继承(案例分析)

我们从图片中就可以看到,两栖动物它既继承了水生动物的一部分特性,也继承了陆地动物的一些特性,那么我们的代码,会不会也会有这种多继承现象呢,我们一起来看一下。

提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是多继承?

1.单继承

  我们来看一个图先了解一下单继承,再看有什莫区别

一文读懂C++中的继承之菱形继承(案例分析)

也就是说,一个子类只有一个直接父类时称这个继承关系为单继承

2.多继承

一文读懂C++中的继承之菱形继承(案例分析)

我们把 一个子类有两个或以上直接父类时称这个继承关系为多继承

我们看一下代码,看看多继承中存在哪些问题。

//基类A
class A 
{
public:
  A() :m_data(1)
  {
  }
  ~A(){}
 
public:
  int m_data;   //同名变量
  
};
//基类B
class B
{
public:
  B() :m_data(1)
  {
  }
  ~B(){}
 
public:
  int m_data;   //同名变量
  
};
 
class C : public A, public B
{
 
};
 
int main()
{
  C Data;
  //Data.m_data = 10;  //错误, 提示指向不明确 不能够分辨m_data到底是谁的
  //只有通过域成员运算符给其明确指出才可以访问,
  Data.A::m_data = 5; 
  Data.B::m_data =10;
  
  std::cout << Data.A::m_data << "  " << Data.B::m_data << std::endl;
 
  return 0;
}

通过上面的代码我们明显看的出,多继承体系中存在二义性问题。指如果有同名的数据成员 那么就无法直接通过变量名进行读取,需要通过域(::)成员运算符进行区分

就好像一个人说 去给老师送个东西去,那么多老师,你无法确定他所指的是哪一个老师,必须指名道姓,我们才可以区分。一个道理

二、菱形继承

我们先来画张图,理解一下什么叫做菱形继承

一文读懂C++中的继承之菱形继承(案例分析)

我们把这种继承类型叫做菱形继承。

那么这种继承体制,又会出现什么样的问题呢?我们通过下面的代码具体看一下。

// 菱形继承 菱形继承是多继承的一种特殊情况。
//菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。
 
 
class A
{
public:
	int m_a = 1;
};
class B :public A
{
public:
	int m_b = 2;
};
class C :public A
{
public:
	int m_c = 3;
};
class D :public B, public C
{
public:
	int m_d = 4;
};
void main()
{
	D d;
	d.m_d = 40;
	d.m_c = 30;
	d.m_b = 20;
	//.m_a = 10;// 二义性
	// 不能够访问 因为B 和C分别继承了A的m_a
	//但是D 继承了B和C的m_a 所以D不能够分辨m_a到底是谁的
	d.B::m_a = 100;
	d.C::m_a = 200;
	// 这样的话 就造成了m_a 有两个空间 一个B的100 一个C的200
}

一文读懂C++中的继承之菱形继承(案例分析)

我们根据上面的情况不难看出,菱形继承中也存在数据的二义性,这里的二义性是由于他们间接都有相同的基类导致的。 这种菱形继承除了带来二义性之外,还会有有数据冗余浪费内存空间

何为空间浪费,数据冗余,我们画图展示一下。

一文读懂C++中的继承之菱形继承(案例分析)

那么该怎样解决这种问题,

1.虚基类的引入

C++中引入了虚基类,其作用是 在间接继承共同基类时只保留一份基类成员。

我么看一下代码

class A
{
public:
	int m_a = 1;
};
class B :virtual public A
{
public:
	int m_b = 2;
};
class C :virtual public A
{
public:
	int m_c = 3;
};
class D :public B, public C
{
public:
	int m_d = 4;
};
void main()
{
	D d;
	d.m_d = 40;
	d.m_c = 30;
	d.m_b = 20;
	d.m_a = 100;// 让B C虚拟继承 A 加关键字virtual
}

一文读懂C++中的继承之菱形继承(案例分析)

我们可以看到很好解决了二义性和数据冗余的问题,那么它是具体怎么来做的,

2.虚基表的引入

这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到了A。

具体我们画一张图

一文读懂C++中的继承之菱形继承(案例分析)

这里的B  C就像两个人分别在两个不同的地方,但是都要去A这个地方,保存了A的地址,那么就可以用地图去导航,但是因为两个人所在的地方不一样,所以到A的距离肯定也会不一样,也就是A的偏移量肯定会不一样(这样说会比较好理解一点)。

总结

很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有 菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度上就有问题并且菱形继承虚继承也带来了性能上的损耗(因为多开了地址来存放偏移量)。

到此这篇关于C++中的继承之菱形继承的文章就介绍到这了,更多相关C++继承之菱形继承内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

延伸 · 阅读

精彩推荐
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12