名字查找、拷贝控制操作与继承体系

2024-08-26 05:12

本文主要是介绍名字查找、拷贝控制操作与继承体系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

假设继承关系为:c->b->a

名字查找与继承体系

每个类都有自己的作用域,在继承体系中,基类(外部)派生类(内部)遵守嵌套作用域的规则:

  1. 内部作用域会隐藏外部作用域

名字查找:

  1. 如果内部作用域存在,则使用内部作用域
  2. 否则逐层查找外部作用域

继承特殊性:

  1. 派生类包含派生类部分,和直接基类部分,直接基类部分,又包含直接基类部分的直接基类部分……
普通成员函数
  1. 作用域:派生类同名成员和函数(即使形参列表不一致)会 隐藏 基类的成员和函数
  2. 类类型(静态类型):调用静态类型成员
  3. 指针/引用类型(动态类型):调用静态类型成员
虚函数
  1. 作用域:派生类同名成员和函数(形参列表必须一致)会 覆盖 基类的成员和函数
  2. 类类型(静态类型):调用静态类型成员
  3. 指针/引用类型(动态类型 & 动态绑定):调用动态类型成员,如果动态类型中没有覆盖,逐层向上查找

注意:除了虚函数的覆盖外,尽量不要定义同名的普通成员和函数

重载和继承:
  1. 如果派生希望基类所有重载版本都是可见,要么全部覆盖,要么一个也不覆盖
  2. 如果覆盖每个函数及其繁琐,可使用using  类::函数名(不用指定形参列表),
  3. 这样就会将所有重载函数添加到派生类中,而派生类只需要定义特有的函数

拷贝控制操作与继承体系

如果一个类没有合成拷贝控制操作,派生类不会继承基类的函数,而是编译器会为派生类合成默认的版本

删除的函数和继承
  1. 如果基类的拷贝控制操作被delete或private,则派生类对应的合成操作也定义为delete的,但如果想要拥有这些操作,可以自定义自己的版本
  2. 如果基类折构函数为delete或private,派生类的默认构造和拷贝构造和移动构造为delete
构造函数
  1. 在默认情况下,创建派生类对象,会自动调用派生类构造函数,而构造函数会调用直接基类的默认构造函数,初始化派生类对象中的基类部分,也可以显示的在初始化列表调用特定的基类构造
  2. //
  3. 如果创建一个派生类,会调用直接基类的构造函数,直接基类的构造又会调用直接基类的直接基类的构造,逐层向上……,最后执行最顶端基类的函数体,逐层向下……,
  4. 当执行基类的构造时,派生类部分是处于未被初始化状态,因此我们不能在基类构造调用派生类的构造,
  5. //
  6. 如果一个类没有合成拷贝控制操作,派生类不会继承基类的函数,而是编译器会为派生类合成默认的版本,但是我们可以使用using继承基类所有的构造函数(默认,拷贝,移动……)
  7. 对于基类每个函数,using会让编译器生成每个对于的派生类构造函数(形参列表是完全相同的)
  8. ……
拷贝 ||  移动构造 & 拷贝 ||  移动赋值
  1. 如果想要拷贝构造 操作,必须在派生类对应的初始值列表,显示调用基类的拷贝 || 移动 函数,否则派生类对象中的基类部分,将执行基类的默认构造函数,这个新的对象会变得非常奇怪
  2. b ( const b& x) : a(x)  &   b(b&& x) : a(std::move(x))
  3. 同样移动也需要显示调用,在重载=运算符函数中
  4. b& operator=( const b& x){ a::operato=(x) }
  5. //
  6. 定义了拷贝构造,编译器不会为我们定义默认的移动构造
  7. 如果没有移动操作,我们实际使用的是拷贝操作
折构
  1. 对于动态new分配的基类的指针,当delete时,会调用构造函数,但是在继承体系中,一个基类指针为动态类型,因为它可以指向派生类对象,
  2. 那么如果想要执行正确版本(派生类)的折构函数,需要将基类的折构函数声明为virtual
  3. 否则如果一个基类的折构函数不是virtual,则delete指向派生类对象的基类指针将产生未定义行为
  4. //
  5. 如果一个类定义了虚折构函数,则派生类中无论默认的还是自定义的都为虚折构函数
  6. 如果一个类定义了虚折构函数,则不一定需要拷贝和赋值操作
  7. 如果一个类定义了折构函数,则不会为这个类合成移动操作
  8. 当执行基类的折构函数时:执行顺序从派生类开始,逐层向上,直至继承链的最顶端(在构造中一个派生类包含上层的所有直接间接基类,树中的一条自底向上的路径,所以销毁直至最顶端)
  9. 折构函数不需要显示调用派生类的,它会隐式销毁派生类自己的成员,还会自动的隐式销毁直接基类的成员……

这篇关于名字查找、拷贝控制操作与继承体系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107643

相关文章

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python使用DrissionPage中ChromiumPage进行自动化网页操作

《Python使用DrissionPage中ChromiumPage进行自动化网页操作》DrissionPage作为一款轻量级且功能强大的浏览器自动化库,为开发者提供了丰富的功能支持,本文将使用Dri... 目录前言一、ChromiumPage基础操作1.初始化Drission 和 ChromiumPage

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Redis中管道操作pipeline的实现

《Redis中管道操作pipeline的实现》RedisPipeline是一种优化客户端与服务器通信的技术,通过批量发送和接收命令减少网络往返次数,提高命令执行效率,本文就来介绍一下Redis中管道操... 目录什么是pipeline场景一:我要向Redis新增大批量的数据分批处理事务( MULTI/EXE

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

Oracle存储过程里操作BLOB的字节数据的办法

《Oracle存储过程里操作BLOB的字节数据的办法》该篇文章介绍了如何在Oracle存储过程中操作BLOB的字节数据,作者研究了如何获取BLOB的字节长度、如何使用DBMS_LOB包进行BLOB操作... 目录一、缘由二、办法2.1 基本操作2.2 DBMS_LOB包2.3 字节级操作与RAW数据类型2.

JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)

《JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)》本文介绍了如何在Windows系统上配置多版本JDK(以JDK8和JDK17为例),并通过图文结合的方式给大家讲解了详细步骤,具有... 目录第一步 下载安装JDK第二步 配置环境变量第三步 切换JDK版本并验证可能遇到的问题前提:公司常

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth