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

news/2024/11/22 22:50:48/

文章目录

  • 一、多继承 " 弊端 "
    • 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 类对象 dD 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 类对象 dD d;// 访问 继承自 A 类的 x 成员不会出现二义性d.x = 40;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
}

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


http://www.ppmy.cn/news/1197008.html

相关文章

2023-11-04:用go语言,如果n = 1,打印 1*** 如果n = 2,打印 1*** 3*** 2*** 如果n = 3,打印

2023-11-04:用go语言,如果n 1,打印 1*** 如果n 2,打印 1***3*** 2*** 如果n 3,打印 1***3*** 2***4*** 5*** 6*** 如果n 4,打印 1***3*** 2***4*** 5*** 6***10** 9*** 8*** 7*** 输入…

【ElasticSearch系列-05】SpringBoot整合elasticSearch

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631【三】ElasticSearch的高级查询Quer…

力扣 搜索旋转排序数组 二分

&#x1f468;‍&#x1f3eb; 33. 搜索旋转排序数组 class Solution {public int search(int[] nums, int target){int l 0;int r nums.length - 1;while (l < r){int m l r >> 1;//else大法&#xff0c;把无序段抛给else&#xff0c;if只处理有序段 // 需要特…

蓝桥杯官网练习题(正则问题)

题目描述 考虑一种简单的正则表达式&#xff1a; 只由 x ( ) | 组成的正则表达式。 小明想求出这个正则表达式能接受的最长字符串的长度。 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是&#xff1a; xxxxxx&#xff0c;长度是 6。 输入描述 一个由 x()| 组成的正则表…

Git 案例(企业如何使用git开发项目)

一、企业中我们是如何开发 1) 入职第一天,管理人员分配/git账号密码 2) 开发人员下载代码即文档/ 根据文档将环境搭建成功 3) 团队一般会给你讲讲项目相关的支持 4) 你接到第一个需求(或者某个功能,一般要经过沟通,分析,设计...等过程) 5) 创建feature分支(一般一个需求对应…

在Qt中解决opencv的putText函数无法绘制中文的一种解决方法

文章目录 1.问题2.查阅资料3.解决办法 1.问题 在opencv中&#xff0c;假如直接使用putText绘制中文&#xff0c;会在图像上出现问号&#xff0c;如下图所示&#xff1a; 2.查阅资料 查了一些资料&#xff0c;说想要解决这个问题&#xff0c;需要用到freetype库或者用opencv…

k8s:endpoint

在 Kubernetes 中&#xff0c;Endpoint 是一种 API 对象&#xff0c;它用于表示集群内某个 Service 的具体网络地址。换句话说&#xff0c;它连接到一组由 Service 选择的 Pod&#xff0c;从而使它们能够提供服务。每个 Endpoint 对象都与相应的 Service 对象具有相同的名称&am…

vs的使用技巧

vs的使用技巧 1.快捷键&#xff1a;2.代码编辑&#xff1a;3.调试&#xff1a;4.代码导航&#xff1a;5.代码重构&#xff1a;6.解决方案资源管理器&#xff1a;7.自定义设置&#xff1a;8.插件扩展&#xff1a;9.团队合作&#xff1a;10.学习资源&#xff1a; Visual Studio&a…