大家好
欢迎回来继续学习
C++语言程序设计
接下来呢
我们再来看看单目运算符
怎么重载
还有这个前置++
后置++怎么区分呢
那么如果我们要重载一个
单目运算符
比如说我们用代号U表示
某种单目运算符
需要将这样的单目运算符
重载为类的成员函数
那它又分前置单目运算符
和后置单目运算符
首先呢
我们来看
前置单目运算符的重载规则
那么前置单目运算符
它要实现的表达式呢
就是运算符在前
操作数在后
比如说
我们这里用U oprd
来代表
其中这个oprd是A类的对象
那么这个时候
我们可以将U
重载为A类的成员函数
这个时候呢
是不需要形参的
因为只有一个操作数
这个操作数就是类的对象
这个时候如果我们去
在程序中写U oprd
这样的表达式
就相当于通过oprd这个对象
去调用operatorU这个函数
那么如果我们要为后置的++
和--
重载运算符函数
它与前置++ - -的运算符函数
差别在哪儿呢
我们知道
如果说两个函数的名字相同
要能够区分它们的话
那只能用参数表来区分了
因为不管前置++ 后置++
它的运算符都是两个+号
那么这就决定了
它的重载函数名
都必须是operator++
也就说函数名是一样的了
这个时候要区分哪个是前置的
哪个是后置的
当然只能通过参数表
所以呢
后置的自增自减运算符
它的重载函数的参数表
里面的参数
要比前置的多一个参数
而多的这个参数呢
就只用来区分
它是一种不同的重载形式
在函数体中是不能使用它的
所以当我们在程序中
出现了后置++的
这种表达式的时候
就相当于通过对象
去调用operator++函数
但是实参给了它一个整数0
下面这个例子呢
就通过时钟类来演示了
如何将前置++和后置++
都重载为时钟类的成员函数
前置的单目运算符重载的时候
函数是没有形参的
这个我们刚刚知道了
而后置的运算符呢
重载函数
需要有一个int类型的形参
那么在这道例题中呢
操作数就是时钟类的对象
clock类的对象
时间的功能不管是前置++
还是后置++
我们都要求它实现
时间加1秒钟的功能
我记得大家在一开始
学习基本的算术运算的时候
有很多同学
一直存下了一个疑惑
这个前置++和后置++
它到底是怎么实现的这个差别呢
而且有的同学可能甚至就
到底也弄不清楚
它到底差别在哪儿
通过这个例题
通过我们自己写一个函数
来分别实现前置++
写另一个函数实现后置++
这样呢
我们就会彻底地明白
到底这两者实现上
有什么不同
现在我们来看一下
这个例题的原代码
现在我们在时钟类中
重载了两个自增运算符函数
第一个是前置自增的运算符
所以呢
它是参数表中是没有参数的
因为是单目前置运算符
那第二个是后置++运算符
为了区分前置与后置
那么它们的参数表必须不同
所以语法上规定
当重载后置自增运算符的时候
参数表里面
要有一个int类型的参数
但是这个参数
它的目的只是为了区分
它是一个后置的运算符
那么在实现的时候
函数体中
是不应该去使用这个参数的
好 那这个钟表类的定义呢
我们回顾一下
首先它的构造函数中
要判断数据的合法性
然后呢
用参数值去初始化
当前对象的数据成员
然后showTime显示时间
现在看我们刚刚增加的
这个运算符重载函数
先看前置自增运算符
它实现加1秒的功能
那么时间加1秒以后呢
要判断是不是秒数大于等于60了
如果是的话呢
秒数减掉60分加1
如果分钟大于等于60分钟了
那么这么
minute就减60
然后小时数加1
因为用的是24小时制
所以小时数加1以后
还要对24取余
那最后呢
返回当前对象
那么这个前置自增呢
它的运算结果
也就是它的函数的返回值
应该是一个本类对象的引用
也就是说
它返回的是个左值
我们知道前置自增是先增1
后使用
所以使用的就是它返回的那个值
当然得返回它自己
所以应该是个引用
那么再看这个后置加1
后置加1呢
我们说是先使用后加1
这是一个
不太准确的形象的说法
在第二章中
我们讲前置 后置
自增自减运算符的时候呢
这样简单地解释
大家可能心里还有些疑问
什么叫先加1后使用
什么叫先使用后加1呢
到底是怎么实现的呢
肯定做这个自增运算符的时候
它都加1了
那现在我们来看
我们自己写一个实现
后置自增运算的函数
大家就清楚了
那么现在呢
我们要首先将当前对象目前的值
也就是*this
当前对象目前的值
暂时存储在
一个临时的局部变量里面
这个old
然后对当前对象实行加1的运算
那么这个加1
当然我们把上面这段程序
拷贝过来
但是这个不是好办法
比较好的办法就是说
我们直接调用这个前置自增运算符
这样的话呢
都是加1
两边的算法就能够统一了
如果你两个函数体都是单独写的
那么它的算法有可能
在几经修改以后
就变得不一致了
比如说
现在我们使用24小时制的
你可以把代码复制过来
可是后面经过修改
可能想改成12小时制
但是这两处有一处忘了改
那么它就实现功能的方式
就不一致了
所以为了避免这种情况呢
我们比较好的方案就是
让这个后置自增运算
直接调用这个
前置的自增运算函数
所以将当前对象前置++自增1
然后
这个函数的返回结果是什么呢
关键在这儿
返回的结果呢
是刚才存起来的这个
原来没有加1的时间
存在old里面了
将old返回
所以现在我们看到
这两个函数的差别吧
这个返回的是加1以后的那个数
所以呢
这个返回值
再继续参与其他更复杂范围
更大范围的运算的时候
用的是加1以后的那个值
而这个函数返回的是
没有加1的那个旧的值
所以它再去参与
更大范围的运算的时候呢
用的是那个没有加1的旧的值
但是其实这时候
它自己已经暗地里加了1了
这就是前置加1和后置加1
它实现上的差别
现在大家可以理解
一个前置自增运算符
我们说它先加1再使用
那么后置自增运算符
它先使用加1
其实这个说法不是很确切
其实使用的时候
它已经被加1了
只不过使用的是
它没加1之前
就复制出来的那个副本
所以实现的原理是这样的
还有呢
由于这个后置+1
它使用的是
这个对象的一个副本
而不是这个对象自己
所以它返回的是一个右值
所谓右值就是通过这个值
你是不能去改变这个对象的
因为它返回的就是一个复制品
你通过这个复制品
你用这个值没有问题
你触及不到这个对象本身
而前置++呢
它返回的就是对象本身
那么返回值
是当前对象的这个引用
所以通过这个引用
你可以直接操纵这个对象的
所以这是前置++和后置++
它的另一个不同点
就是它的运算结果
前置的它是一个左值
后置的自增
它的运算结果是一个右值
实际上
就是它原来对象的一个副本
现在呢
我们来看在主函数中验证一下
构造了一个时钟类对象
把时间初始化在23点59分59秒
然后我们显示一下这个时间
在这儿调用showTime显示一下
接下来呢
就调用后置自增运算
实际上就调用了这个operator
后置自增这个函数
调用完了以后
大家看这个返回的结果
就应该放在这个括号里面了
通过这个返回的结果
去调用showTime
而这个返回结果
是myClock自己吗
绝对不是
我们看到返回的结果
是myClock自己的一个副本
所以通过这个临时的副本
调用showTime
看到的时间是什么呢
是它还没有加1之前的时间
因为它还没有加1之前的时间
放在旁边存着
然后把这个副本返回了
它自己加1了
但是并没有把加1的这个值返回
所以呢
我们在这里看到的
是没有加1之前的这个数据
接下来呢
我们再调用前置++运算
那么这回呢
基础是什么
基础是
这个原来的23点59分59秒
已经经过后置++增了1秒
变成0点0分0秒了
在这个基础上再加1
而且返回的
就是加1以后的这个结果
所以两次加1的效果
都反映在这次输出里面了
我们看到输出的是0点0分1秒
因为它返回的
是加1以后的自己
所以通过这个例题
我想大家不仅学会了
编写前置自增
后置自增的这个运算符重载函数
也对前置和后置的运算符
有了更清楚地理解