要实现运算符的重载必须对运算符的功能重新定义,C++中定义功能只能采用函数的形式,所以实际上运算符重载就是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型确定需要调用的函数,这个过程是在编译过程中完成的。
▶5.5.3.1 运算符重载函数的定义
运算符重载函数的定义,在成员函数和友元函数两种形式下的语法有所不同。
(1)运算符重载函数为成员函数,其语法形式如下:
其中,operator是定义运算符重载函数的关键字,<运算符>为要重载的运算符,<参数表>中最多有一个形参,这是因为成员函数是由该类的对象调用的,所以其中的一个参数值是由调用该函数的对象给出的,另一个参数由形参给出。因此,如果重载运算符为单目运算符,则参数表为空,一个操作数直接由对象给出;若为双目运算符,则左操作数由对象给出,右操作数由参数表给出,参数表只有一个类类型的形参。
(2)运算符重载函数为友元函数,其语法形式如下:
其中,friend为友元函数关键字,operator为定义运算符重载函数的关键字,<运算符>为要重载的运算符,<参数表>最多有两个形参。
因为友元函数不属于类,所以函数的参数均由函数的形参给出。因此,如果重载运算符为单目运算符,参数表为一个形参;若为双目运算符时,参数表只有两个类类型的形参。
单目运算一般定义为成员函数,所以,单目运算除了对象以外没有其他参数,那么重载如“++”和“--”这样的单目运算符时,如何区分是前缀操作如“++i”还是后缀操作“i++”呢?C++语言约定,为了区分单目运算符的前缀和后缀操作,在定义重载函数时,参数表为空表示前缀;而在参数表中放上一个整型参数,表示后缀运算符。如void operator++()表示前缀,而void operator++(int)表示后缀。这里的int并没有实际含义,只是为了区分前缀和后缀而设立的。
▶5.5.3.2 运算符重载函数的调用
前面讲到重载运算符只是扩充运算符的使用类型,而运算符的基本功能和使用方式应该和预定义的运算符是一样的,所以运算符重载函数的调用实际上是对重载运算符的使用,也和预定义运算符的使用是一样的,但是单目运算符和双目运算符在重载为成员函数和友元函数时系统的解释是不一样的。
(1)单目运算符
单目运算符函数的调用形式如下:
object op或者op object
当重载为成员函数,编译系统将其解释为“object.operator op()”,操作数由对象object通过this指针隐含传递。
当重载为友员函数,编译系统将其解释为“operator op(object)”,操作数由参数表的参数object提供。例4为单目运算符“·”(取相反数)的定义和调用。
运行结果:
the oppsite number is-10
程序分析:void operator-()函数是实现对取反运算符“-”进行重载,主函数中语句“-nl;”是对重载函数的调用,这是因为n1是n类型的对象,系统将其解释为“n1.operator-();”。调用重载函数时,n1为实参,因为nl是类对象,所以可以判断调用的是重载函数而不是预定义取反运算。
而函数内value=-value中“-”运算符的操作数value是预定义int型,所以“-”是预定义运算符。由此可以总结出,如果预定义运算符的类型是类类型,则其使用的是运算符重载功能,如果是基本数据类型则使用的是预定义运算符的预定义功能。
这个例子是用成员函数的方式进行运算符重载的。当然也可以用友元函数的方式进行重载,更改重载函数如下:
friend void operator-(n&obj) //单目运算符-重载为友元函数的定义(www.xing528.com)
{obj.value=-obj.value;} //此处的“-”是预定义运算符
当重载为友员函数,编译系统将其解释为“operator op(object)”,操作数由参数表的参数object提供。所以程序运行时,-nl将被解释为“operator-(n1)”,参数传递将实参对象nl传递给形参对象obj,执行“nl.value=-nl.value”,故而nl.print在执行完后的结果仍为“the oppsite number is-10”。
从这个例子进一步可以说明,重载既可以用成员函数的方式进行,也可以以友元函数的方式进行。但需注意它们使用和调用方式的不同。
需要注意:当重载为友员函数时,要用对象的引用作为函数的参数。
(2)双目运算符
双目运算符函数的调用形式如下:
Leftobject op Rightobject
当重载为成员函数时,解释为“Leftobject.operator op(Rightobject)”,左操作数由Leftobject通过this指针传递,右操作数由参数Rightobject传递。
当重载为友员函数时,解释为“operator op(Leftobject.Rightobject)”,左右操作数都由参数传递。例5重载加法运算可以对复数进行加法运算。
例5:
程序分析:首先系统分别为对象cl,c2,c调用构造函数,语句c=cl+c2中操作数均为complex类类型,所以该语句调用重载运算符函数complex operator+(complex c1),实参为cl和c2,系统将其解释为cl.operator+(c2),实现c1.real+c2.real和c1.imag+c2.imag,从而实现cl+c2的运算。
该重载函数也可以用友元函数的方式进行,将重载函数定义如下:
friend complex operator+(complex&c1,complex&c2)//
友元重载加法运算符“+”
双目运算在重载为友员函数时,被解释为“operator op(Leftobject,Rightobject)”,左右操作数都由参数传递,所以函数中分别用对象cl和c2的引用做参数。执行调用语句c=c1+c2时,系统将其解释为operator+(c1,c2),实现c1.real+c2.real和c1.imag+c2.imag,从而实现两个复数对象的加法运算。
▶5.5.3.3 使用成员函数和友元函数的区别
(1)对双目运算符而言,成员运算符函数带有一个参数,而友元运算符函数带有两个参数;对单目运算符而言,成员运算符函数不带参数,而友元运算符函数带一个参数。
(2)双目运算符一般可以被重载为友元运算符函数或成员运算符函数。
(3)成员运算符函数和友元运算符函数可以用习惯方式调用,也可以用它们专用的方式调用。也就是说重载函数的调用有如下两种形式:
这两种方式完全等价。一般地,为了符合使用习惯,通常用习惯调用方式,如:
这样,无论是系统预定义的运算符功能还是重载运算符功能,使用时都可以采用同样的方式,方便掌握。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。