【C++】多态 ⑫ ( 多继承 “ 弊端 “ | 多继承被禁用的场景 | 菱形继承结构的二义性 | 使用虚继承解决菱形继承结构的二义性 )

文章目录

  • 一、多继承 " 弊端 "
    • 1、多继承被禁用的场景
    • 2、多继承弊端
  • 二、代码示例 - 多继承弊端
    • 1、错误示例 - 菱形继承结构的二义性
    • 2、代码示例 - 使用虚继承解决菱形继承结构的二义性






一、多继承 " 弊端 "



1、多继承被禁用的场景


禁止使用多继承的场景 : 在 C++ 语言 环境 中 , 多继承 若干完整的 有成员函数 和 成员变量 的 类 , 是不推荐的做法 , 实际开发中 , 绝对禁止 使用 上述类型的 多继承 ;


2、多继承弊端


多继承会带来一系列的问题 , 诸如 :

  • 钻石问题 - 菱形继承结构 / 二义性错误 : 当一个类继承自多个类时 , 如果这些类有共同的基类 , 那么会出现菱形继承结构 , 也称为钻石问题 ; 该场景下 , C++ 编译器 无法确定应该使用哪个基类的成员 , 产生 二义性 ;
  • 成员变量名相同 - 二义性错误 : 子类继承多个父类 , 父类之间没有相同的父类 , 但是 父类中 有相同名称的成员变量 , 此时也会产生二义性问题 , 需要使用域作用符访问父类中相同名称的成员 ;
  • 破坏封装性 : 多继承 可能会破坏类的封装性 , 由于一个类需要实现多个基类的接口 , 因此它必须公开更多的实现细节 , 这可能会降低代码的可维护性和可重用性 ;
  • 复杂的构造和析构过程 : 多继承 的 子类 的 构造和析构过程 可能会变得非常复杂 , 当一个子类对象被创建时 , 需要调用所有基类的构造函数 ; 当一个对象被销毁时 , 需要调用所有基类的析构函数 ; 构造 和 析构 期间 , 可能会导致资源泄漏或程序崩溃等问题 ;
  • 应用二进制接口 ABI 兼容性问题 : 多继承可能会导致 ABI ( 应用二进制接口 Application Binary Interface ) 兼容性问题 , 不同的 编译器和操作系统可能会有不同的ABI规范 , 这可能会导致在不同的平台上使用不同的编译器编译的代码时出现问题 ;

使用 虚继承 解决二义性问题 ;

在 菱形继承结构 中 , 虚继承可以使 重复继承 的 父类 , 只继承 依次 ;


多继承的二义性 参考 【C++】继承 ⑫ ( 继承的二义性 | virtual 虚继承 ) 博客 ;

在这里插入图片描述





二、代码示例 - 多继承弊端




1、错误示例 - 菱形继承结构的二义性


在下面的 菱形继承结构 中 , D 继承 B 和 C 类 ,

但是 B 和 C 有共同的 父类 A ,

假如 访问 D 对象 中 继承自 A 类的成员 , 会产生二义性 ;


代码示例 :

#include "iostream"
using namespace std;

class A {
public:
	int x;
};

// 子类 B 继承了父类 A 的 x 成员
class B : public A {
public:
	int y;
};

// 子类 C 继承了父类 A 的 x 成员
class C : public A {
public:
	int z;
};

// D 多继承 B 和 C 
// 分别从 B 和 C 各自继承一个来自 A 的成员 x
class D : public B, public C {
public:
	int k;
};

int main() {

	// 定义 D 类对象 d
	D d;

	// 访问 继承自 A 类的 x 成员出现二义性
	// 报错 error C2385: 对“x”的访问不明确
	d.x = 40;
	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>Y:\002_WorkSpace\002_VS\HelloWorld\HelloWorld\Test.cpp(35,6): error C2385: 对“x”的访问不明确
1>Y:\002_WorkSpace\002_VS\HelloWorld\HelloWorld\Test.cpp(35,6): message : 可能是“x”(位于基“A”中)
1>Y:\002_WorkSpace\002_VS\HelloWorld\HelloWorld\Test.cpp(35,6): message : 也可能是“x”(位于基“A”中)
1>已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
在这里插入图片描述


2、代码示例 - 使用虚继承解决菱形继承结构的二义性


在下面的 菱形继承结构 中 , D 继承 B 和 C 类 ,

但是 B 和 C 有共同的 父类 A , 这里 B 和 C 使用 虚继承 , 继承 A 类 ;

假如 访问 D 对象 中 继承自 A 类的成员 , 不会产生二义性 ;


代码示例 :

#include "iostream"
using namespace std;

class A {
public:
	int x;
};

// 子类 B 继承了父类 A 的 x 成员
class B : virtual public A {
public:
	int y;
};

// 子类 C 继承了父类 A 的 x 成员
class C : virtual public A {
public:
	int z;
};

// D 多继承 B 和 C 
// 分别从 B 和 C 各自继承一个来自 A 的成员 x
class D : public B, public C {
public:
	int k;
};

int main() {

	// 定义 D 类对象 d
	D d;

	// 访问 继承自 A 类的 x 成员不会出现二义性
	d.x = 40;
	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :
在这里插入图片描述

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

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

相关文章

C++ Qt 学习(二):常用控件使用与界面布局

1. Qt 布局详解 ui 设计器设计界面很方便,为什么还要手写代码? 更好的控制布局更好的设置 qss代码复用 完全不会写 Qt 布局,很麻烦,怎么学会手写布局? 看 Qt 自己怎么写改良 Qt 的布局写法 1.1 水平布局 #include …

C++笔记之vector的成员函数swap()和data()

C笔记之vector的成员函数swap()和data() 标准C中的std::vector类确实有swap()和data()这两个成员函数。下面是它们的简要描述: swap(): std::vector的swap()成员函数用于交换两个向量的内容,实现了高效的交换操作,不需要复制向量的元素。这…

Apache HttpClient库编写的Scala程序

Apache HttpClient库编写的Scala下载器程序,用于下载图片。代码如下: import org.apache.http.HttpHost import org.apache.http.client.HttpClients import org.apache.http.client.methods.HttpHead import org.apache.http.impl.client.CloseableHtt…

纠结蓝桥杯参加嵌入式还是单片机组?

纠结蓝桥杯参加嵌入式还是单片机组? 单片机包含于嵌入式,嵌入式不只是单片机。. 你只有浅浅的的单片机基础,只能报单片机了。最近很多小伙伴找我,说想要一些单片机资料,然后我根据自己从业十年经验,熬夜搞了几个通宵…

MCU HardFault_Handler调试方法

一.获取内核寄存器的值 1.在MDK的DEBUG模式下,当程序出现跑飞后,确定卡死在HardFault_Handler中断处 2. 通过Register窗口读取LR寄存器的值来确定当前系统使用堆栈是MSP还是PSP LR寄存器值堆栈寄存器0xFFFFFFF9MSP寄存器0xFFFFFFFDPSP寄存器 如下图所…

【SpringCloud Alibaba -- Nacos】Linux 搭建 Nacos 集群

搭建 Nacos 集群 架构 centos安装docker https://docs.docker.com/engine/install/centos/ 详细配置过程 MySql8 mysql数据库配置 数据库脚本 nacos/conf/nacos-mysql.sql Nacos2 application.properties 修改为mysql spring.datasource.platformmysqldb.num1 db.url…

中国等28个国家发布《布莱切利宣言》,鼓励AI以安全方式发展

英国时间11月1日,中国、美国、英国、法国、德国等28个国家和欧盟,在英国的布莱切利庄园签署了,首个全球性人工智能(AI)声明——《布莱切利宣言》。 该宣言明确指出了AI对人类社会的巨大机遇,但AI需要以人为…

Python 包管理器入门指南

什么是 PIP? PIP 是 Python 包管理器,用于管理 Python 包或模块。注意:如果您的 Python 版本是 3.4 或更高,PIP 已经默认安装了。 什么是包? 一个包包含了一个模块所需的所有文件。模块是您可以包含在项目中的 Pyth…

Chatgpt批量改写文章网页版可多开软件-自动登录换号生成word或者TXT

Chatgpt批量改写文章网页版可多开软件介绍: 1、改写后生成docx格式文档和生成txt文档二选一。 2、支持原来docx文档里带图片的改写,改写伪原创后的docx里也带图片。 3、软件可以设置是否开启标题改写,可以自定义标题改写指令。 4、可以设置…

全功能测试框架 - Carina

Carina是一个基于Java的测试自动化框架,它将所有测试层结合在一起:移动应用程序(web、本机、混合)、web应用程序、REST服务和数据库。 github:GitHub - zebrunner/carina: Carina automation framework (TestNG): Web…

ubuntu 20.04 + cuda-11.8 + cudnn-8.6+TensorRT-8.6

1、装显卡驱动 ubuntu20.04 cuda10.0 cudnn7.6.4_我是谁??的博客-CSDN博客 查看支持的驱动版本: 查看本机显卡能够配置的驱动信息 luhost:/usr/local$ ubuntu-drivers devices/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 moda…

uniapp新建的vuecli项目启动报错并且打包失败的问题(已解决)

我的项目新建流程如下 运行之后就是如下报错 解决办法: 安装如下依赖: npm i postcss-loader autoprefixer8.0.0 npm run build 编译失败 安装如下依赖: npm install postcss8.2.2 最终package.json文件如下 {"name": "ls…

【STL】:list的模拟实现

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关list的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据…

asp.net docker-compose添加volume配置

打开docker-compose.override.yml下面添加 volumes:killsb-one-sqldata:external: false 服务下面添加volume配置 volumes:- "./dapr/config/social-client.json:/app/OidcSettings.json" 添加volume配置成功

图片复制上传,拖拽输入框上传,el-upload自定义上传方法(上传和备注框强关联)

1. 效果图&#xff1a; 2. 复制图片使用的方法&#xff1a; 1.通过监听paste方法&#xff0c;获取复制内容2.获取复制内容中的clipboardData3.获取file文件进行上传 <input paste.native"handlePaste" />handlePaste(value){let files value.clipboardData…

网络基础扫盲-初识网络

博客内容&#xff1a;初识网络 文章目录 一、OSI七层网络模型二、TCP/IP四层模型1、MAC地址与IP地址 前言 在以前网络不够发之前&#xff0c;各个实验室进行一些研究时需要进行数据的交流&#xff0c;但是那时车马很慢&#xff0c;一生只够跑几次&#xff0c;所以就有人研究了网…

Java医院HIS系统源码

Java医院HIS系统源码 项目描述 该项目是用springbootlayuishiro写的医院管理系统&#xff0c;该系统的业务比较复杂&#xff0c;数据库一共有36张表。项目的视频业务参考文档&#xff0c;都在百度云盘中。可以先看看视频和参考文档。 运行环境 jdk8mysqlIntelliJ IDEAmaven…

IntelliJ IDEA 2023 最新版如何试用?IntelliJ IDEA 2023最新版试用方法及验证ja-netfilter配置成功提示

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

SOEM源码解析——ec_init(初始化单网卡主站)

0 工具准备 1.SOEM-master-1.4.0源码1 ec_init总览 /** Initialise lib in single NIC mode:初始化库在单网卡模式* param[in] ifname Dev name, f.e. "eth0" 设备名* return >0 if OK* see ecx_init*/ int ec_init(const char * ifname) {return ecx_init(&…