C++继承(二):菱形继承、virtual菱形虚拟继承

目录

一、了解菱形继承

二、菱形继承的问题 

三、虚拟继承virtual

3.1virtual

3.2虚拟继承解决数据冗余和二义性的原理

四、总结/继承和组合 


一、了解菱形继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

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

 菱形继承:菱形继承是多继承的一种特殊情况。

二、菱形继承的问题 

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。
在Assistant的对象中Person成员会有两份。

class Person
{
public:string _name; // 姓名
};
class Student : public Person
{
protected:int _num; //学号
};
class Teacher : public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name = "peter";// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";
}
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和 Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地
方去使用。

三、虚拟继承virtual

3.1virtual

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和
Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地
方去使用。
class Person
{
public:string _name; // 姓名
};
class Student : virtual public Person
{
protected:int _num; //学号
};
class Teacher : virtual public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{Assistant a;a._name = "peter";
}

3.2虚拟继承解决数据冗余和二义性的原理

为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成
员的模型。
class A
{
public:int _a;
};
// class B : public A
class B : virtual public A
{
public:int _b;
};
// class C : public A
class C : virtual public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};
int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}
下图是 菱形继承 的内存对象成员模型:这里可以看到数据冗余:
下图是 菱形虚拟继承 的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下
面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指
向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量
可以找到下面的A

 原理图

四、总结/继承和组合 

1. C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱
形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设
计出菱形继承。否则在复杂度及性能上都有问题。
2. 多继承可以认为是C++的缺陷之一,很多后来的OO语言都没有多继承,如Java。
3. 继承和组合
首先在日常代码的编写过程中,经常遵循一个理念: 高内聚低耦合。
1.public继承是一种 is-a 的关系。也就是说每个派生类对象都是一个基类对象。
2.组合是一种 has-a 的关系。假设B组合了A,每个B对象中都有一个A对象。
3.优先使用对象组合,而不是类继承 。
4.继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称
为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的
内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很
大的影响。派生类和基类间的依赖关系很强,耦合度高
5.对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象
来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复
用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被
封装。
6.实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有
些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用
继承,可以用组合,就用组合。
// Car和BMW Car和Benz构成is-a的关系
class Car {
protected:string _colour = "白色"; // 颜色string _num = "豫A88888"; // 车牌号
};class BMW : public Car {
public:void Drive() { cout << "好开-操控" << endl; }
};class Benz : public Car {
public:void Drive() { cout << "好坐-舒适" << endl; }
};// Tire和Car构成has-a的关系class Tire {
protected:string _brand = "Michelin";  // 品牌size_t _size = 17;         // 尺寸};class Car {
protected:string _colour = "白色"; // 颜色string _num = "豫A88888"; // 车牌号Tire _t; // 轮胎
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python-自动化篇-终极工具-用GUI自动控制键盘和鼠标-pyautogui

文章目录 用GUI自动控制键盘和鼠标pyautogui 模块鼠标屏幕位置——移动地图——pyautogui.size鼠标位置——自身定位——pyautogui.position()移动鼠标——pyautogui.moveTo拖动鼠标滚动鼠标 键盘按下键盘释放键盘 开始与结束通过注销关闭所有程序 用GUI自动控制键盘和鼠标 在…

【教学类-48-03】202402011“闰年”(每4年一次 2月有29日)世纪年必须整除400才是闰年)

2000-2099年之间的闰年有25次&#xff0c; 背景需求&#xff1a; 已经制作了对称年月的数字提取&#xff0c;和年月日相等的年份提取 【教学类-48-01】20240205对称的“年”和“月日”&#xff08;如2030 0302&#xff09;-CSDN博客文章浏览阅读84次。【教学类-48-01】202402…

专业140+总分410+华南理工大学811信号与系统考研经验华工电子信息与通信,真题,大纲,参考书。

23考研已经落幕&#xff0c;我也成功的上岸华工&#xff0c;回首这一年多的历程&#xff0c;也是有一些经验想和大家分享一下。 首先说一下个人情况&#xff0c;本科211&#xff0c;初试成绩400分。专业课140。 整体时间安排 对于考研&#xff0c;很重要的一环就是时间安排&…

《动手学深度学习(PyTorch版)》笔记8.5

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

python基于flask的网上订餐系统769b9-django+vue

课题主要分为两大模块&#xff1a;即管理员模块和用户模块&#xff0c;主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等&#xff1b; 如果用户想要交换信息&#xff0c;他们需要满足双方交换信息的需要。由于时间有限…

使用C#快速创建一个非常实用的桌面应用程序

过节时和我年纪轻轻就一把年纪的弟弟张老二闲聊了许久&#xff0c;发现他对编程产生了一泡浓厚的兴趣&#xff0c;于是我就给他漏了一手C#&#xff0c;做了一个简单的适用于win-x64配置cpu的桌面应用程序。 步骤如下&#xff1a; 1.打开Visual Studio,点击新建项目&#xff0…

C#,泰波拿契数(Tribonacci Number)的算法与源代码

1 泰波拿契数&#xff08;Tribonacci Number&#xff09; 泰波拿契数&#xff08;Tribonacci Number&#xff09;是斐波那契的拓展。 泰波拿契数 (Tribonacci Number) 即把费波拿契数 (Fibonacci Number) 的概念推广至三个数。 2 计算结果 3 源程序 using System; namespace…

Linux笔记之Docker进行镜像备份与迁移

Linux笔记之Docker进行镜像备份与迁移 ——2024-02-11 code review! 文章目录 Linux笔记之Docker进行镜像备份与迁移1. 导出容器文件系统为 tar 归档文件2. 将 tar 归档文件导入为新的 Docker 镜像3. 运行新的 Docker 镜像并创建容器 1. 导出容器文件系统为 tar 归档文件 要导…

前端JavaScript篇之异步编程的实现方式?

目录 异步编程的实现方式&#xff1f;1. 回调函数2. Promise3. Async/Await4. Generator 异步编程的实现方式&#xff1f; 异步编程是处理需要等待的操作的一种方式&#xff0c;比如读取文件、发送网络请求或处理大量数据。在JavaScript中&#xff0c;有几种常见的实现方式&am…

C#系列-C#log4net日志保存到文件(15)

在C#中使用log4net将日志保存到文件是一个常见的做法。log4net是一个功能强大的日志记录框架&#xff0c;它允许你配置日志的输出格式、级别、目标&#xff08;例如文件、控制台、数据库等&#xff09;等。 下面是如何配置log4net以将日志保存到文件的基本步骤&#xff1a; 安…

Codeforces Round 924 (Div. 2)(A~B)

A. Rectangle Cutting 给你一个长方形x*y&#xff0c;其中x*y 和 y*x认为是一样的&#xff0c;问你对这个长方形进行对半切然后进行拼接&#xff0c;是否能得到一个不一样的长方形p*q。 #include <bits/stdc.h> //#define int long long #define per(i,j,k) for(int (i…

数据容器的通用操作

my_num[1,3,5,6,3,5] 1.print(len(my_num)) #统计容器的元素个数 2.print(max(my_num)) #统计容器的最大元素 3.print(min(my_num)) #统计容器的最小元素 4.容器的类型转换: 例如&#xff1a; age[19,18,20,54,67,43,21] print(set(age)) #将容器转集合 print(str(age))#…

【力扣 1232】缀点成线 C++题解(向量+数学)

给定一个数组 coordinates &#xff0c;其中 coordinates[i] [x, y] &#xff0c; [x, y] 表示横坐标为 x、纵坐标为 y 的点。请你来判断&#xff0c;这些点是否在该坐标系中属于同一条直线上。 示例 1&#xff1a; 输入&#xff1a;coordinates [[1,2],[2,3],[3,4],[4,5],…

腾讯云4核8G服务器价格,性能如何?

腾讯云4核8G服务器S5和轻量应用服务器优惠价格表&#xff0c;轻量应用服务器和CVM云服务器均有活动&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;标准型SA2服务器1444.8元一年&#xff0c;轻量应用服务器4核8G12M带宽一…

《UE5_C++多人TPS完整教程》学习笔记1 ——《P2 关于本课程(About This Course)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P2 关于本课程&#xff08;About This Course&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译者&…

探索设计模式:原型模式深入解析

探索设计模式&#xff1a;原型模式深入解析 设计模式是软件开发中用于解决常见问题的标准解决方案。它们不仅能提高代码的可维护性和可复用性&#xff0c;还能让其他开发者更容易理解你的设计决策。今天&#xff0c;我们将聚焦于创建型模式之一的原型模式&#xff08;Prototyp…

ubuntu中尝试安装ros2

首先&#xff0c;ubuntu打开后有个机器人栏目&#xff0c;打开后&#xff0c;有好多可选的&#xff0c;看了半天 ,好像是博客&#xff0c;算了&#xff0c;没啥关系&#xff0c;再看看其他菜单 这些都不是下载链接。先不管&#xff0c;考虑了一下&#xff0c;问了ai&#xff…

【正则表达式的妙用】

题目&#xff1a; 给定一个字符串&#xff0c;折叠操作的定义为&#xff1a; 1、对其中连续的字符可以进行删除字符操作&#xff0c;但要保证至少保留其中1个字符&#xff1b; 2、一次可以对多个不同的连续字符进行删除字符操作 如给定字符串 “abbbcccbbbeeef”, 通过折叠…

数据库恢复

文章目录 前言一、事务1.概念2.定义语句3.ACID特性 二、数据库恢复的必要性1.为什么要进行数据库恢复2.数据库恢复机制的作用 三、数据恢复使用的技术1.数据转储2.登记日志文件 四 、不同故障的数据恢复策略1.事务内部的故障2.系统故障3.介质故障 五、具有检查点的恢复技术1.检…

接口测试--apipost接口断言详解

在做接口测试的时候&#xff0c;会对接口进行断言&#xff0c;一个完整的接口测试&#xff0c;包括&#xff1a;请求->获取响应正文->断言。 一、apipost如何进行断言 apipost的断言设置实在后执行脚本中进行编写的。apipost本身提供了11中断言&#xff1a; apt.asser…