运算符重载(operator overload)
运算符重载
可以为运算符增加一些新的功能
+ 的运算符重载
场景运用:希望获取两个坐标相加后得到的新坐标
按照之前的思路应该会是如下代码:
当然对于addPoint
这个函数来说就是将两个坐标的x和y分别相加后得到一个新的坐标,那么更简单已读的一定是使用+
来表达,类似于p1 + p2
,如果是这样就要运用到运算符重载了
很简单只要如下图这样做即可
但其实运算符重载也是一个函数,只不过名字比较特殊,p1 + p2
其实等价于operator+(p1, p2)
,这一点在汇编代码中也可以看的明白
但是上面写的+重载的函数并不严谨,对象作为参数直接传入的话会调用拷贝构造函数产生中间对象,所以对象类型作为参数并不好,应该使用引用类型并且加上const
会使参数接收范围更广,如下:
下一步的优化是将运算符重载函数放入Point类中当做成员函数
但是还有一个问题,先看下面代码,这样是将10
赋值给30
显然不合理
但是我们代码现在是可以这样,p1+p2产生的一个匿名对象,而且还给这个匿名对象赋值其实没什么意义,如同上述例子所讲,所以应该禁止这样做
修改让返回值是常量对象即可解决上述问题
但是如上修改会造成多个点相加会出错
这个原因就是const
对象只能调用const
成员函数或者static
函数,所以要讲重载函数声明为const
成员函数
拷贝构造函数的一点疑问
刚才的问题让人联想到拷贝构造函数的格式一直是个固定的,今天来探究下为何如此,假如是下面这样:
Point(Point p) {
}
如果不使用引用类型会造成死循环的问题,因为在使用Point p2 = p1
这样的语句时就会调用拷贝构造函数,但是在当p1
作为参数传入时其实是Point p = p1
,这时又会调用拷贝构造函数并将p1
作为参数传入,这样就会陷入死循环,所以要使用引用类型,其次加上const
后既可以接收const
参数也可以接收非const
参数
- 运算符重载
同+
运算符重载一样,如下
+= 运算符重载
返回值和参数都使用引用类型就是防止产生额外的对象
== 运算符重载
声明成const
函数是可以让const
对象也可以使用
!= 运算符重载
同上面 ==
运算符重载
单目运算符重载
- 运算符重载
就是负号的意思,将点的x
和y
坐标都取反
返回值是const是因为int a = 10; (-a) = 20
这样本身就不可以,另外函数类型是const是确保(-(-a))
可以正常运算
++ 运算符重载
首先明确++
运算符有前置和后置的区分
从汇编可以看出二者的区别:
前置++
是先执行a = a + 1
然后再将加过1
的a
放在那里与5
相加后置++
是先将a
中的10
取出与5
相加后才执行a = a + 1
所以前置++
可以进行赋值操作而后置++
不可以,所以重载也要遵循这个规则
前置++ 运算符重载
后置++ 运算符重载
输入输出运算符重载
<< 输出运算符重载
>> 输入运算符
与输出运算符重载不同的是Point
参数不能带有const
,因为输入这里本来就是要修改Point
参数
调用父类的重载运算符
重载运算符的本质也是函数,直接在子类中调用父类的重载运算符即可
总结:
-
有些运算符不可以被重载
- 对象成员访问运算符
:
- 域运算符
::
- 三目运算符
?:
sizeof
- 对象成员访问运算符
-
有些运算符只能重载为成员函数
- 赋值运算符:
=
- 下标运算符:
[]
- 函数运算符:
()
- 指针访问成员:
->
- 赋值运算符: