如何解决多继承下的 菱形继承 问题

简介: 如何解决多继承下的 菱形继承 问题

概念:

8c2aaddf248048c0a6601b5e1df68605.jpg

此时D类属于多继承,可以看到D类里面会有两份A类的数据,菱形继承也并不一定就一定就是上图的菱形,假如B类下面还有一个类,D类继承它,同样也是菱形继承问题

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 data;
  cout << data.a << endl;
  return 0;
}

 大家觉得这段代码有问题嘛?

8b189ba85da940dbb7cdeafc5883362e.jpg

我们此时D类已经出现了数据冗余和二义性的问题了,我们直接访问 a 的值是不可行的,只有明确地表明你要访问地是哪个类里面的 a

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 data;
  cout << data.a << endl;
  return 0;
}

不过可以在腰部,也就是 B和C 类加上 virtual ,就可以数据二义性的问题和数据冗余,这个叫 菱形虚拟继承


菱形虚拟继承:

class A
{
public:
  int a;
};
//class B : virtual public A
class B : public A
{
public:
  int b;
};
//class C : virtual public A
class C : public A
{
public:
  int c;
};
class D : public B, public C
{
public:
  int d;
};
int main()
{
  D data;
  //data.a = 1;
  data.B::a = 2;
  data.C::a = 6;
  data.b = 3;
  data.c = 4;
  data.d = 5;
  return 0;
}

 我们来看一下上述代码运行完,在内存的角度观察他们的变化:

5c0e72ed051c4577ac7b1208bfc042b3.jpg

能够看的出,总共分为三个部分:上面两个框分别是B和C类的,谁先继承谁就在上面,并且,数据a 也是独立开来的,B里面a = 2;C里面a = 6 。

再来看加了virtual后的又会是什么样的变化:

7cef93b9c8d44c838040c0d88c1291a0.jpg

同样也是分为了三个部分,先继承的类就在上面,所以上面两个分别是B和C类,但这次不一样的是:


数据a并没有分开来,而是在最下面去了,相代替的是一个指针,这个指针指向的是一个虚基表,这个表里面存放着一个偏移量,当我们要进行 切割 的时候,获取 数据a 就通过当前的这个指针 + 这个偏离量就能找到了。(这个表叫虚基表,指针叫虚基表指针)


如果此时定义一个B对象,它的里面同时也有一个续集表指针,指向一个自己的续集表,这个偏移量 和 D定义出来的 对象 里的 B类的虚基表里的偏离量不同 

82d2a27a45cf4a3e8c79c3a6caada71e.jpg如图所示:左边是B类定义出来的对象;右边是D类定义出来的对象。

他们都有各自的虚基表指针,这个指针是不一样的!!!!里面的偏移量也是!!

目录
相关文章
|
Web App开发 存储 关系型数据库
|
人工智能 并行计算 安全
从零到一,打造专属AI王国!大模型私有化部署全攻略,手把手教你搭建、优化与安全设置
【10月更文挑战第24天】本文详细介绍从零开始的大模型私有化部署流程,涵盖需求分析、环境搭建、模型准备、模型部署、性能优化和安全设置六个关键步骤,并提供相应的示例代码,确保企业能够高效、安全地将大型AI模型部署在本地或私有云上。
5367 7
|
Kubernetes 前端开发 Java
使用Docker将服务部署到阿里云的服务器上
利用一个简单的前后端分离项目来介绍Docker在部署过程中的使用。
3569 0
|
机器学习/深度学习 传感器 编解码
基于matlab实现16个调频脉冲信号的产生、脉冲压缩、MTI、MTD、CFAR等信号处理算法
基于matlab实现16个调频脉冲信号的产生、脉冲压缩、MTI、MTD、CFAR等信号处理算法
920 0
|
Kubernetes Apache 流计算
flink-kubernetes-operator 的简单使用
flink-kubernetes-operator 的简单使用
1441 0
PR曲线、ROC曲线、AUC能干个啥
评判二分类分类器性能的指标有那么多,为什么PR曲线、ROC曲线、AUC值这几个用的比较多。本文从概念、代码实现方面着手进行分享。
PR曲线、ROC曲线、AUC能干个啥
|
JSON Prometheus 监控
ClickHouse监控系统Prometheus+Grafana
ClickHouse监控系统Prometheus+Grafana
2718 0
|
JSON Dubbo Java
Feign远程调用
本节基于Feign实现替换RestTemplate发起Http请求,在此过程中会发现技术演进的过程是不断变化的,最初引入RestTemplate的确帮我们解决了跨服务调用,但是随着更为优雅的技术出现时,我们会毫不犹豫去实践更佳的解决方案,这也是我们最初提出单体架构-->分布式架构的演变过程。 本节希望能重点关注Feign提出的初衷,最佳实践,并能够结合最佳实践在日后工作中得以落地。
|
存储 算法 小程序
408操作系统学习笔记——内存管理(一)
408操作系统学习笔记——内存管理
694 1
408操作系统学习笔记——内存管理(一)
|
存储
408计算机组成原理学习笔记——总线
408计算机组成原理学习笔记——总线
649 1
408计算机组成原理学习笔记——总线

热门文章

最新文章