当前位置: 首页 > news >正文

C++中菱形类关系再理解

很多很多年前,还在北京读研时,我去 magnetar 寻求一个实习机会时,面我的北美小哥让我解释一下C++的菱形关系,好像当时没有答上来。

今天在 OceanBase 代码里又看到了菱形关系。多重继承在我们的代码中是很少出现的,居然能再次遇到可真不容易。

问题:下面的代码里,C 的构造函数为什么必须显式调用 Base(v)?

class Base {  explicit A(int &) {} }
class A : virtual public Base { }
class B : virtual public Base { }
class C :  public A, public B 
{
   C(int v) : Base(v), A(), B() {}
}

更进一步地,为什么下面比较简单的场景里 C 依然要显式调用 Base(v)?

class Base {  explicit A(int &) {} }
class A : virtual public Base { }
class C :  public A
{
   C(int v) : Base(v), A() {}
}

Well,有了一些工作经验后会积累一些设计的思想,能够更好地站在设计者角度思考问题。回答上面两个问题就比较容易了:

C++ 设计者引入了一条简单规则:A、B 这样使用了 virtual 继承的对象作为中间类时,没有资格去实例化基类。

还是有点绕,更简单的思维:

A、B 这样使用了 virtual 继承的对象作为中间类时,不会为A、B 分配基类对象的结构。

只要不让他们去分配对象,那么自然就需要子类去分配对象,子类分配了对象,自然就需要主动调用 Base 的构造函数。

C++设计者面对菱形问题时,解决思维如下:

  1. 要避免给基类(Base)分配多份内存
  2. 所以子类 A、B 都不应该去给基类(Base)分配内存
  3. 所以内存只能由 A、B 的子类 C 去分配内存
  4. 所以 C 需要调用构造函数。

然后遇到一个特殊情况:

  1. 如果 Base 只有一个子类 A,A 只有一个子类 C,那么 A 能不能为 Base 分配内存呢?
  2. 这里如果考虑极致优化,此时可以让 A 给 Base 分配内存,C无需关注 Base。
  3. 但是这样做太特殊。所以设计者保持了一致的用户接口:Base 的内存必须由 C 分配。

相关文章:

  • stack和queue的使用和模拟实现
  • 【C++】 string类常用接口的实现
  • 华为防火墙基础自学系列 | 汇总
  • TNet 中 JoinChannel 场景名可写可不写
  • 使用容器编译Yocto镜像
  • 【uniapp】小程序中修改Vant组件navbar左箭头的颜色及图标
  • 【区块链 | 智能合约】如何编写一个可升级的智能合约
  • java毕业设计开题报告javaweb户籍管理系统|户口
  • 交换机堆叠+链路聚合+浮动静态路由
  • (分布式缓存)Redis持久化
  • 计算机组成原理第二章----数据信息的表示 详解版(写的这么接地气我一下就懂了?)
  • windows 常用命令字典
  • 【案例回顾】春节一次较波折的MySQL调优
  • IDEA2020创建JavaSE项目改造成JavaWeb项目并配置tomcat
  • 分布式任务调度Schedulerx2.0工作原理
  • [笔记] php常见简单功能及函数
  • 10个确保微服务与容器安全的最佳实践
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Android系统模拟器绘制实现概述
  • Angular 响应式表单 基础例子
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • E-HPC支持多队列管理和自动伸缩
  • Java 网络编程(2):UDP 的使用
  • Javascript基础之Array数组API
  • JS笔记四:作用域、变量(函数)提升
  • JS专题之继承
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 关于Flux,Vuex,Redux的思考
  • 经典排序算法及其 Java 实现
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 悄悄地说一个bug
  • 深度学习在携程攻略社区的应用
  • 事件委托的小应用
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 通过git安装npm私有模块
  • 小程序button引导用户授权
  • 正则学习笔记
  • C# - 为值类型重定义相等性
  • hi-nginx-1.3.4编译安装
  • MPAndroidChart 教程:Y轴 YAxis
  • ​io --- 处理流的核心工具​
  • #Linux(权限管理)
  • $jQuery 重写Alert样式方法
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (TOJ2804)Even? Odd?
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转载)Google Chrome调试JS
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • /etc/X11/xorg.conf 文件被误改后进不了图形化界面
  • [AIGC] 如何建立和优化你的工作流?
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)