(根据《C++程序设计》(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明)
1 什么是运算符重载
先来说下什么是重载吧!所谓重载,就是赋予新的含义。重载包括函数重载和运算符重载。函数重载就是对一个已有的函数赋予新的含义,使之实现新的功能,因此,同一个函数名就可以用来代表不同功能的函数,也就是一名多用。函数重载在以后的博客中会陆续介绍,这个系列先只介绍运算符重载。
运算符也可以重载,实际上,我们已经在不知不觉中使用了运算符重载。例如,大家大家已经习惯于用加法运算符“+”对整数、单精度数和双精度数进行加法,其实,计算机处理整数、单精度数和双精度数加法的操作方法是不同的,由于C++已经对运算符“+”进行了重载,使“+”能适用于int、float、double类型的不同的运算。
现在要讨论的问题是:用户能否根据自己的需要对C++已经提供的运算符进行重载,赋予它们新的含义,使之一名多用。例如,能否用“+”号进行两个复数的相加。在C++中是不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。
最容易想到的方法是:自己定义一个专门的函数来实现复数相加。例如:
1: class Complex //定义Complex类
2: {
3: public:
4: ...
5: Complex complex_add( Complex& c2 ) ; //声明复数相加函数
6: private:
7: double real ; //实部
8: double imag ; //虚部
9: };
10:
11: Complex Complex :: complex_add( Complex& c2 ) //定义复数相加函数
12: {
13: Complex c ;
14: c.real = real + c2.real ;
15: c.imag = imag + c2.imag ;
16: return c ;
17: }
此方法采用在Complex类中定义complex_add函数,其作用是将两个复数相加,在该函数体中定义一个Complex类对象c作为临时对象。其中的赋值语句相当于
1: c.real = this->real + c2.real ;
2: c.imag = this->imag + c2.imag ;
this是当前对象的指针。
利用上述方法得到的结果是正确的,但调用很不方便。人们自然会想到:能否也和整数的加法运算一样,直接用“+”来实现复数运算,这就需要对“+”进行重载。
2 运算符重载的方法
运算符重载的方法是定义一个重载运算符的函数,使指定的运算符不仅能实现原有的功能,而且还能实现函数中指定的新功能。在使用被重载的运算符时,系统就自动调用该函数,以实现相应的功能。运算符的重载实质上是函数的重载。
运算符重载的一般格式如下:
函数类型 operator 运算符名称(形参表)
{ 对运算符的重载处理 }
在上面的一般格式中,operator是关键字,是专门用于定义重载运算符的函数的,函数名使用operator和运算符组成。
例,对运算符“+”进行重载,使之能用于两个复数相加:
1: class Complex
2: {
3: public:
4: ...
5: Complex operator + ( Complex& c2 ) ; //声明重载运算符 + 的函数
6: private:
7: double real ;
8: double imag ;
9: };
10:
11: Complex Complex :: operator + ( Complex& c2 ) //定义重载运算符 + 的函数
12: {
13: Complex c ;
14: c.real = real + c2.real ;
15: c.imag = imag + c2.imag ;
16: return c ;
17: }
经过这样的声明和定义之后,若c1、c2、c3都是Complex类的对象,在进行两个复数相加时,就可以这样:
1: c3 = c1 + c2 ;
将运算符"+"‘重载为类的成员函数后,C++编译系统将程序中的表达式"c3=c2+c1"解释为" c1.operator + ( c2 ) ",表示以c2为实参调用c1的运算符重载函数operator+,进行两个复数相加。
通过以上的比较可以看到,无论是通过自定义complex_add函数,还是重载“+”运算符,两个程序的结构和执行过程基本上是相同的,作用相同,运行结果也相同。那为什么还要进行运算符重载呢?这就要从用户的角度来思考问题,虽然重载运算符所实现的功能完全可以由函数实现,但是使用运算符重载能使用户易于编写、阅读和维护。
注意:运算符被重载后,其原有的功能仍然保留,没有丧失或改变。也就是说同一个运算符可以代表不同的功能,当编译系统需要判别该执行哪一个功能的时候,是根据表达式的上下文决定的,即根据运算符两侧的数据类型来决定的。
总结一下:本来C++提供的运算符只能用于标准类型数据的运算,但C++程序设计的重要基础是类和对象,如果C++的运算符无法用于类和对象,则类和对象的应用将会受到很大的限制。为了解决这个问题,使类和对象有更强的生命力,C++允许重载现用的运算符,使这些简单易用、众所周知的运算符能直接应用于自己定义的类和对象。
3 重载运算符的规则
(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(2)C++允许重载的运算符。
记住不能重载的运算符:
成员访问运算符: .
成员指针运算符:*
作用域运算符: ::
长度运算符:sizeof
条件运算符:?:
(3)重载不能改变运算符运算对象的个数。
如关系运算符“<”“>”等是双目运算符,重载后仍为双目运算符,需要两个参数。有些运算符既可以作为单目运算符,也可以作为双目运算符,这就需要分别重载。
(4)重载不能改变运算符的优先级别。
(5)重载不能改变运算符的结合性。
(6)重载运算符的函数不能有默认的参数。否则就改变了运算符参数的个数,与(3)矛盾。
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类的对象或类的引用。也就说参数不能全是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(8)用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。