运算符重载(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
- 对象成员访问运算符
-
有些运算符只能重载为成员函数
- 赋值运算符:
= - 下标运算符:
[] - 函数运算符:
() - 指针访问成员:
->
- 赋值运算符: