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

【C++】入门【六】

本节目标


一、继承的概念及定义

二、基类和派生类对象赋值转换

三、继承中的作用域

四、派生类的默认成员函数

五、继承与友元

六、继承与静态成员

七、复杂的菱形继承及菱形虚拟继承

八、继承的总结和反思

九、笔试面试题


一、继承的概念及定义

1.继承的概念

  • 继承是面向对象程序设计中是代码可以复用的手段,允许了程序员在原有的类特性上进行扩展,增加功能,这样产生新的类,称为派生类
  • 继承呈现了面向对象程序设计的层次结构
  • 以前我们接触的复用都是函数复用,继承是类设计层次方面的复用
  • 用例如下
  • bdcc36140248446bb49a9a89b63230c7.png
  • b56e79cbb34c4029aacb8cc2d83512e0.png
  • f9d72ecc1a044605aa14fd1b15322d6a.png
  • f9dca081ff95495fbb7654ad77b6fa35.png

2.继承的定义

  • 父类跟子类,也叫基类跟派生类
  • 9715aba4d47947ebaddcdbf89b1aa1b9.png
  • 继承关系和访问限定符:
  • 继承又分为三种继承关系 public protected private
  • 117a2ccee68a43cabaa9e75b8127e34c.png
  • 继承后子类对父类的访问又分为三种 public protected private
  • 3a2e1eafbf2744a59bc9457e7aed6f67.png
  • 948fe2d84ffb44c4b107de35321aec04.png
  • 如果父类也就是基类,里面的函数和变量都是private的,
  • 那么子类/派生类继承后,也无法访问到父类里面的函数和变量
  • 如果父类里面是protected和private 就可以访问
  • protected比较特殊,跟private的不同是,private的所有东西子类和类外都不可以访问
  • 而protected则是 子类可以访问,类外不可以访问
  • 实际中我们都使用public继承,很少使用其他两种
  • 22b480e4b6844b419b1dcd714e7a3c75.png

二、基类和派生类对象赋值转换

  • 派生类可以赋值给基类的对象/指针/引用
  • 但是基类不可以赋值给派生类对象
  • 但是基类的指针/引用可以通过强制类型转换来赋值给派生类的指针/引用
  • 派生类赋值给基类时,其实基类是把派生类里自己的东西拿走,其他的东西不拿走,换个说法也叫切割或者切片,就是把派生类中基类的东西切掉赋值过去
  • 切割如图所示(子类student里父类的东西切割 送过去)
  • 60f5ef062710455abe1bf962ec7fc681.png
  • a93ab7bf1b574b03adb566e89988ed97.png
  • 925bd6410d854e109394a09aa3b5a2c5.png
  • 13ec51da1123400183b640ee047c672e.png
  • 8f1413e1bf2a48c1a9375258cc6c7623.png

三、继承中的作用域

  • 在继承体系中,基类和派生类都有自己的作用域
  • 如果基类和派生类中有同名成员, 子类将屏蔽父类的成员,这种情况叫做隐藏,也叫重定义
  • 如果不想屏蔽掉,想使用同名成员里的父类的,可以通过使用基类::基类成员来进行访问使用
  • 只要函数名相同就构成隐藏,不管返回值类型
  • 在继承体系中最好不要定义同名成员
  • 这里不展示类详细信息,看结论 
  • b652cb90e66a423588e4356110703257.png
  • 2d8ab253334d4d99b6f66aa270b246d8.png

四、派生类中的默认成员函数

  • 还是6个默认成员函数
  • 父类里面的成员变量 必须 通过父类的构造函数来初始化,子类不能初始化
  • 90f1842aff9b4a18921787b79b249d31.png
  • 36630b5de4024d948c0b9680c6fcf7d2.png

五、继承和友元

  • 友元关系不能继承
  • 基类的友元不能访问子类的私有成员和保护成员
  • 9e276280bf874bf3ad455e62788a7ea5.png

六、继承与静态成员

  • 基类如果定义了static静态成员,则整个继承体系里只有一个这样的成员
  • 子类也共用,无论派生出多少子类,都只有一个static成员
  • 额外补充 注意: static静态成员在类中声明,类外初始化 类外初始化不用加static
  • 比较简单,这里不做演示

七、复杂的菱形继承及菱形虚拟继承

1.各种继承

  • 单继承
  • 一个子类只有一个直接父类就叫单继承
  • 986036799fd04c34817337c80f08797a.png
  • 多继承
  • 一个子类有两个及以上直接父类叫多继承
  • eeeecd692d604be3aee8b58cb7a90d41.png
  • 菱形继承
  • 菱形继承是多继承的一种特殊情况
  • 361df89e21874f758ec3622989d91827.png
  • 关于菱形继承 有着很大的问题,由于多继承的出现就导致了菱形继承
  • 观察上图
  • student和teacher两个类继承了person 
  • 而assistant又同是继承了他俩
  • 那么在assistant里面 就有了两个同名的成员变量,此时如果访问的话,编译器就不知道是访问的谁的 student还是teacher的
  • 547b5ccdfe1c4a6388726ea46b62eba9.png
  • 1506156575ce44bba8f576c951b1936a.png
  • bec9efe2eaec4a0d98234ba8dd1b548a.png

2.虚拟继承

  • 为了解决掉这个问题
  • 此时出现了虚拟继承
  • 虚拟继承可以解决菱形继承中的二义性和数据冗余
  • 在上面的student和teacher 继承 person时加上virtual 即可解决问题
  • d748552b4fbc4810bfac325728b67c30.png
  • 注意:虚拟继承不要在其他地方使用 仅限于菱形继承

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

  • 为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系
  • 569f0cc9d9a74b04806e59ed0a4e9acb.png
  • 58273d912f634ce98f33e89b6d186f00.png
  • 191e1dc337e94987922ed1515628fadc.png
  • cd4475e76900404f96d96ce880d71169.png
  • a3f5fe7ae85e404985949e290b3aaefb.png

八、继承的总结和反思

  • 很多人说C++语法复杂,其实多继承就是一个体现,有了多继承,就存在了菱形继承,有了菱形继承就有了虚拟继承,底层实现就很复杂,所以一般不建议设计出多继承,在java里面是没有多继承的,菱形继承一定不要设计出来,复杂性太高
  • 多继承可以认为是C++的缺陷之一
  • 继承和组合
  • 继承是is的关系,组合是has的关系
  • 优先使用组合,而不是继承
  • 什么是组合? 下图  这里没用继承 将轮胎给到了车上
  • ce2b6237657c46ca83b3c267bd0f630a.png

九、笔试面试题

  • 1.什么是菱形继承?菱形继承的问题是什么?
  • 661b2a31fc414cd59a2d1909043a4309.png
  • 2.什么是菱形虚拟继承,如何解决数据冗余和二义性的?
  • a9acf3e8c238494bb2b690b1e6f7cfca.png
  • c4df5950ba3b4ba691b60cabcf643aa9.png
  • 3.继承和组合的区别?什么时候用继承?什么时候用组合?
  • 23bac4d61546476e9f203eb388e84751.png

 

 


http://www.mrgr.cn/news/79191.html

相关文章:

  • 智能穿戴设计灵感:用 AI 创作女款圆形创意表盘
  • 导游现场面试需要注意的问题
  • SPT: Revisiting the Power of Prompt for Visual Tuning
  • net.core SignalR web Socket ws
  • Java 设计模式~工厂模式
  • 硬件成本5元-USB串口采集电表数据完整方案-ThingsPanel快速入门
  • 数字IC前端学习笔记:脉动阵列的设计方法学(以串行FIR滤波器为例)
  • 优傲协作机器人 Remote TCP Toolpath URCap(操作记录)
  • L17.【LeetCode笔记】另一棵树的子树
  • 【OpenDRIVE_Python】使用python脚本输出OpenDRIVE数据中含有隧道tunnel的道路ID和隧道信息
  • SCP命令实现Linux中的文件传输
  • Qt Quick 开发基础 + 实战(持续更新中…)
  • Vue3 Ts 如何获取组件的类型
  • 【OpenDRIVE_Python】使用python脚本输出OpenDRIVE数据中含有桥梁bridge的道路ID和桥梁信息
  • cgo内存泄漏排查
  • 微信小程序版小米商城的搭建流程详解!
  • Springboot 2.x 升级到Springboot 2.7.x问题汇总
  • mysql集群NDB方式部署
  • 基于python爬虫的智慧人才数据分析系统
  • string类函数的手动实现
  • mysql中的skip_name_resolve详解
  • 速通SpringBoot+vue全栈开发教程
  • 贪心算法题
  • Python3:pytest+request+yaml+allure接口自动化测试
  • <工具 Claude Desktop> 配置 MCP server 连接本地 SQLite, 本机文件夹(目录) 网络驱动器 Windows 11 系统
  • 4. IO Stream