文章目录
- 运算符重载的概念
- 运算符重载(函数)
- 返回值类型:任意类型
- 函数名:operator已有操作符
- 运算符重载(函数)的特点和注意点
- 3个比较特殊的运算符重载
- 赋值运算符(=)重载
- 返回值类型和返回值
- 参数
- 函数体
- ++运算符重载(- -运算符重载类似)
- 前置++
- 前置++的返回值:
- 前置++的函数体
- 后置++
- 后置++的返回值:
- 参数表:
- 后置++的函数体
- <<运算符重载(>>运算符重载类似)
- <<运算符重载函数的返回值
- <<运算符重载函数的参数表
- <<运算符重载函数的函数体
运算符重载的概念
运算符重载,就是对
已有
的运算符重新进行定义,增加
其另一种功能,以适应不同的数据类型
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有返回值类型,函数名以及参数列表
其返回值类型与参数列表与普通的函数类似。
运算符重载(函数)
通过 运算符重载(函数)即可让已有的运算符
增加一种运算方式(规则)
运算符重载函数的函数体中的代码,就是运算方式(规则)
返回值
就是运算算的结果
【例:自定义的日期类,如果想计算某一个日期之后n天是什么日期,就可以重载已有的+运算符,让它增加一种日期+天数的运算方式(规则)】
返回值类型:任意类型
根据运算符重载(函数)的作用,自定义
返回值类型和返回值
函数名:operator已有操作符
例
运算符重载(函数)的特点和注意点
-
运算符重载(函数)的参数的相对位置【左,右】,就是操作符的左操作数和右操作数
-
不能
创建新的运算符,只能重载已有的运算符
例
-
运算符重载
不会也不能改变
原运算符的优先级
和结合性
例:重载运算符+之后,+的优先级不变,还是在乘除之后。结合性也没变,还是左结合 -
运算符重载函数的参数表中
至少有一个
参数是自定义类型
因为运算符重载不允许修改
原内置的运算符的运算规则
,而如果参数都是内置类型就是在修改原内置的运算符的运算规则
,而并非增加运算规则
例
-
运算符重载函数可以是
全局函数
,也可以是成员函数
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数是隐藏的this -
::
sizeof
条件运算符?:
点运算符.
.*
这5个运算符不能重载
3个比较特殊的运算符重载
赋值运算符(=)重载
赋值运算符重载其实也是类的默认成员函数
,它的作用就是给对象赋值
也就是说如果程序员没有显式地实现赋值运算符重载,编译器也会自动生成
一个默认的赋值运算符重载
这个默认的赋值运算符重载函数只实现了浅拷贝
返回值类型和返回值
返回值类型是自定义类型(类)的引用
,返回值为*this
原因:
- 返回引用就
不用
调用拷贝构造,可以提高效率 - 可以
链式编程
(即连续赋值 例:a=b=c,因为赋值运算符右结合,所以c先赋值给b,并返回b的引用,返回的b的引用再赋值,相当于a=b)
参数
显式的参数
只有一个,一般为该类的对象的引用
因为赋值运算符只能
重载为成员函数,所以还有一个隐式的参数
是每个成员函数都有的this
指针
函数体
一般为两部分:
-
判断
显式传入
的那个参数是不是this指向的
如果是就是this指向的对象赋值给this指向的对象,也就是自己赋值给自己,没有必有,所以直接返回 -
执行拷贝
如果成员没有
申请资源,就直接浅拷贝
【此时不显式实现赋值运算符(=)重载,直接使用编译器给的默认的也可以】
如果有成员申请了资源
,就必须显式地实现深拷贝
例
++运算符重载(- -运算符重载类似)
++运算符既可以重载为成员函数,又能重载成全局函数
前置++
其实我们常念的口诀:前置++,先++后使用
中的使用,使用的是前置++运算的结果,也就是返回值
前置++的返回值:
必须是++后的参数的引用
原因:
-
保证一直对同一个对象进行运算,我们常常使用++之后的结果直接作为另一个操作符的操作数
例 (++a)+=3,++a返回了a的引用,才能把后面的+=3加等到a上
而直接返回对象的值,返回的是它拷贝构造后的一个东西,并非++之前的对象【地址不一样
】 -
返回引用可以不用调用拷贝构造,可以提高效率
前置++的函数体
一般分为两部分
- 执行对象+=1的操作
- 返回对象的引用
例
后置++
常念的口诀:后置++,先使用,后++
中的使用,使用的是后置
++运算的结果,也就是返回值
后置++的返回值:
返回值:传入的参数的临时拷贝
原因:
要先使用后++,所以后置++的返回值要是参数刚传入函数时的值
,但是后置++函数也要完成++的操作所以需要一个临时的对象存储参数刚传入的值,最后再返回这个对象
又因为是在函数中创建的对象,函数结束就销毁
,所以不能
返回它的引用
参数表:
重载为成员函数
时:operator++(int)
重载为全局函数
时:operator++(要++的对象的引用,int)
为什么要有int这个占位类型?
因为后置++是前置++的重载,=如果参数表相同,就没法重载
所以规定
后置++运算符重载时
用int占位参数区分它和前置++的重载函数
后置++的函数体
一般分为三部分
- 拷贝构造出返回的对象
- 执行++的操作
- 返回拷贝构造出的对象
例
<<运算符重载(>>运算符重载类似)
<<运算符重载,主要实现把对象输出
到屏幕/文件等,一般用cout指执行输出
<<运算符只能
重载成全局函数
为什么呢?
因为如果把<<运算符重载为成员函数,因为this是所有成员函数隐式的第一个参数
那么cout就只能是第二个参数
此时函数参数的相对位置是this在左,cout在右,而运算符重载函数的参数的相对位置,决定左右操作数是谁
所以把<<运算符重载为成员函数时,this(对象)
是左操作数
,cout
是右操作数
也就是重载之后,我们要这样输出对象: a<<cout
不符合我们的习惯
<<运算符重载函数的返回值
返回值类型:ostream&
【ostream是C++标准库中的输出流类,我们常用的cout就是它实例化的对象】
返回值:ostream
实例化的对象的引用
原因:
- 返回
ostream
实例化的对象的引用可以达成链式编程【即 这样就可以:cout<<a<<b<<c
了】 - 返回引用不需要调用拷贝构造,可以提高效率
<<运算符重载函数的参数表
operator<<(ostream& out, 要输出的对象的引用)
<<运算符重载函数的函数体
一般分为两部分
- 执行对象的数据输出
- 返回
ostream
实例化的对象的引用
例