类和对象【四】运算符重载

embedded/2024/11/15 0:52:54/

文章目录

  • 运算符重载的概念
  • 运算符重载(函数)
    • 返回值类型:任意类型
    • 函数名:operator已有操作符
  • 运算符重载(函数)的特点和注意点
  • 3个比较特殊的运算符重载
    • 赋值运算符(=)重载
      • 返回值类型和返回值
      • 参数
      • 函数体
    • ++运算符重载(- -运算符重载类似)
      • 前置++
        • 前置++的返回值:
        • 前置++的函数体
      • 后置++
        • 后置++的返回值:
        • 参数表:
        • 后置++的函数体
    • <<运算符重载(>>运算符重载类似)
      • <<运算符重载函数的返回值
      • <<运算符重载函数的参数表
      • <<运算符重载函数的函数体

运算符重载的概念

运算符重载,就是对已有的运算符重新进行定义,增加其另一种功能,以适应不同的数据类型
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有返回值类型,函数名以及参数列表
其返回值类型与参数列表与普通的函数类似。

运算符重载(函数)

通过 运算符重载(函数)即可让已有的运算符增加一种运算方式(规则)

运算符重载函数的函数体中的代码,就是运算方式(规则)

返回值就是运算算的结果

【例:自定义的日期类,如果想计算某一个日期之后n天是什么日期,就可以重载已有的+运算符,让它增加一种日期+天数的运算方式(规则)】


返回值类型:任意类型

根据运算符重载(函数)的作用,自定义返回值类型和返回值


函数名:operator已有操作符


在这里插入图片描述


运算符重载(函数)的特点和注意点

  1. 运算符重载(函数)的参数的相对位置【左,右】,就是操作符的左操作数和右操作数

  2. 不能创建新的运算符,只能重载已有的运算符

    在这里插入图片描述

  3. 运算符重载不会也不能改变原运算符的优先级结合性
    例:重载运算符+之后,+的优先级不变,还是在乘除之后。结合性也没变,还是左结合

  4. 运算符重载函数的参数表中至少有一个参数是自定义类型
    因为运算符重载不允许修改原内置的运算符的运算规则,而如果参数都是内置类型就是在修改原内置的运算符的运算规则,而并非增加运算规则

    在这里插入图片描述

  5. 运算符重载函数可以是全局函数,也可以是成员函数
    作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数是隐藏的this

  6. :: sizeof 条件运算符?: 点运算符. .* 这5个运算符不能重载


3个比较特殊的运算符重载

赋值运算符(=)重载

赋值运算符重载其实也是类的默认成员函数,它的作用就是给对象赋值

也就是说如果程序员没有显式地实现赋值运算符重载,编译器也会自动生成一个默认的赋值运算符重载

这个默认的赋值运算符重载函数只实现了浅拷贝


返回值类型和返回值

返回值类型是自定义类型(类)的引用,返回值为*this
原因:

  1. 返回引用就不用调用拷贝构造,可以提高效率
  2. 可以链式编程
    (即连续赋值 例:a=b=c,因为赋值运算符右结合,所以c先赋值给b,并返回b的引用,返回的b的引用再赋值,相当于a=b

参数

显式的参数只有一个,一般为该类的对象的引用
因为赋值运算符只能重载为成员函数,所以还有一个隐式的参数是每个成员函数都有的this指针

在这里插入图片描述


函数体

一般为两部分:

  1. 判断显式传入的那个参数是不是this指向的
    如果是就是this指向的对象赋值给this指向的对象,也就是自己赋值给自己,没有必有,所以直接返回

  2. 执行拷贝
    如果成员没有申请资源,就直接浅拷贝此时不显式实现赋值运算符(=)重载,直接使用编译器给的默认的也可以
    如果有成员申请了资源,就必须显式地实现深拷贝


在这里插入图片描述


++运算符重载(- -运算符重载类似)

++运算符既可以重载为成员函数,又能重载成全局函数


前置++

其实我们常念的口诀:前置++,先++后使用
中的使用,使用的是前置++运算的结果,也就是返回值


前置++的返回值:

必须是++后的参数的引用

原因:

  1. 保证一直对同一个对象进行运算,我们常常使用++之后的结果直接作为另一个操作符的操作数
    (++a)+=3,++a返回了a的引用,才能把后面的+=3加等到a上
    而直接返回对象的值,返回的是它拷贝构造后的一个东西,并非++之前的对象【地址不一样

  2. 返回引用可以不用调用拷贝构造,可以提高效率


前置++的函数体

一般分为两部分

  1. 执行对象+=1的操作
  2. 返回对象的引用


在这里插入图片描述


后置++

常念的口诀:后置++,先使用,后++
中的使用,使用的是后置++运算的结果,也就是返回值


后置++的返回值:

返回值:传入的参数的临时拷贝

原因:

先使用后++,所以后置++的返回值要是参数刚传入函数时的值但是后置++函数也要完成++的操作所以需要一个临时的对象存储参数刚传入的值,最后再返回这个对象
又因为是在函数中创建的对象,函数结束就销毁,所以不能返回它的引用


参数表:

重载为成员函数时:operator++(int)
重载为全局函数时:operator++(要++的对象的引用,int)

为什么要有int这个占位类型?
因为后置++是前置++的重载,=如果参数表相同,就没法重载
所以规定后置++运算符重载时
用int占位参数区分它和前置++的重载函数


后置++的函数体

一般分为三部分

  1. 拷贝构造出返回的对象
  2. 执行++的操作
  3. 返回拷贝构造出的对象


在这里插入图片描述


<<运算符重载(>>运算符重载类似)

<<运算符重载,主要实现把对象输出到屏幕/文件等,一般用cout指执行输出

<<运算符只能重载成全局函数

为什么呢?
因为如果把<<运算符重载为成员函数,因为this是所有成员函数隐式的第一个参数
那么cout就只能是第二个参数
此时函数参数的相对位置是this在左,cout在右,而运算符重载函数的参数的相对位置,决定左右操作数是谁
所以把<<运算符重载为成员函数时,this(对象)左操作数cout右操作数
也就是重载之后,我们要这样输出对象: a<<cout
不符合我们的习惯


<<运算符重载函数的返回值

返回值类型:ostream&ostream是C++标准库中的输出流类,我们常用的cout就是它实例化的对象】

返回值:ostream实例化的对象的引用

原因:

  1. 返回ostream实例化的对象的引用可以达成链式编程【即 这样就可以:cout<<a<<b<<c了】
  2. 返回引用不需要调用拷贝构造,可以提高效率

<<运算符重载函数的参数表

operator<<(ostream& out, 要输出的对象的引用)


<<运算符重载函数的函数体

一般分为两部分

  1. 执行对象的数据输出
  2. 返回ostream实例化的对象的引用


在这里插入图片描述


http://www.ppmy.cn/embedded/30147.html

相关文章

C/C++ BM32 合并二叉树

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 树的题目大概率是要用到递归的&#xff0c;将一个树的问题拆分成子树的问题&#xff0c;不断拆分。 这题也用到了递归的思想。 题目 已知两颗二叉树&#xff0c;将它们合并成一颗…

鸿蒙内核源码分析(用栈方式篇) | 程序运行场地谁提供的

精读内核源码就绕不过汇编语言&#xff0c;鸿蒙内核有6个汇编文件&#xff0c;读不懂它们就真的很难理解以下问题. 1.系统调用是如何实现的? 2.CPU是如何切换任务和进程上下文的? 3.硬件中断是如何处理的? 4.main函数到底是怎么来的? 5.开机最开始发生了什么? 6.关机…

每天学习一个Linux命令之file

每天学习一个Linux命令之file 在Linux系统中&#xff0c;有很多强大的命令可用于文件操作和管理。其中一个非常有用的命令是file。file命令可以用于确定文件的类型&#xff0c;它会根据文件的内容进行检测和判断&#xff0c;并输出相应的文件类型信息。在本篇博客中&#xff0…

借助Aspose.SVG图像控件,在线将 PNG 转换为 XML

Aspose.SVG for .NET 是用于SVG文件处理的灵活库&#xff0c;并且与其规范完全兼容。API可以轻松加载&#xff0c;保存和转换SVG文件&#xff0c;以及通过其文档对象模型&#xff08;DOM&#xff09;读取和遍历文件的元素。API独立于任何其他软件&#xff0c;使开发人员无需使用…

python的json序列化和反序列化

在Python中解析JSON数据非常简单&#xff0c;你可以使用内置的json模块。这个模块提供了loads()函数来解析JSON字符串&#xff0c;以及load()函数来解析JSON文件。 import json# JSON字符串 json_str {"name": "John", "age": 30, "city&…

golang 基础知识细节回顾

之前学习golang的速度过于快&#xff0c;部分内容有点囫囵吞枣的感觉&#xff0c;写gorm过程中有很多违反我常识的地方&#xff0c;我通过复习去修正了我之前认知错误和遗漏的地方。 itoa itoa自增的作用在编辑error code时候作用很大&#xff0c;之前编辑springboot的error c…

【Flask 系统教程 3】请求与响应

Flask 是一个灵活而强大的 Web 框架&#xff0c;而请求与响应则是构建 Web 应用的核心组成部分。在本文中&#xff0c;我们将探讨 Flask 中请求与响应的各种用法&#xff0c;包括不同的请求方法、重定向、响应对象、获取查询参数以及文件上传等。 请求 在 Flask 中&#xff0…

打印x型图案Java

KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“*”组成的X形图案。 输入描述&#xff1a; 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜线和正斜线…