9.5.3 以友元函数形式重载运算符

    用成员函数重载双目运算符时,左操作数无须用参数输入,而是通过隐含的this指针传入,这种做法的效率比较高,此外,操作符还可重载为友元函数形式,这将没有隐含的参数this指针。对双目运算符,友元函数有两个参数,对单目运算符,友元函数有一个参数。

    重载为友元函数的运算符重载函数的声明格式如下所示。


    friend返回类型operator运算符(参数表);

    使用友元函数形式重写代码9.7后如代码9.8所示。

    代码9.8 以友元函数形式重载运算符OperatorOverload2


    <—————————————文件名:complex.h————————————————-> 01 #include<iostream> 02 using namespace std; 03 class complex//定义复数类complex 04 { 05 private: 06 double real,imag;//private成员,分别代表实部和虚部 07 08 public: 09 complex(double r=0. 0,double i=0.0)//构造函数,带默认参数值 10 { 11 real=r; 12 imag=i; 13 } 14 friend complex operator+(const complex&,const complex&);//友元函数形式重载加 15 friend complex operator-(const complex&,const complex&);//友元函数形式重载减 16 17 friend complex operator-(const complex&);//友元函数形式重载一元-(取反) 18 friend complex operator*(const complex&,const complex&);//友元函数形式重载乘 19 friend complex operator/(const complex&,const complex&);//友元函数形式重载除 20 friend complex&operator++(complex&);//友元函数形式重载前置 21 friend complex operator++(complex&,int);//友元函数形式重载后置 22 void disp()//成员函数,输出复数 23 { 24 cout<<real<<"+"<<"i*"<<imag<<endl; 25 } 26 }; <——————————————-文件名:complex.cpp——————————————> 27 #include"complex.h"//包含了类complex的定义 28 complex operator+(const complex&C1,const complex&C2)//加的实现 29 { 30 return complex(C1. real+C2.real,C1.imag+C2.imag); 31 } 32 complex operator-(const complex&C1,const complex&C2)//减的实现 33 { 34 return complex(C1. real-C2.real,C1.imag-C2.imag); 35 } 36 complex operator-(const complex&C1)//单目-,即取反的实现 37 { 38 return complex(-C1. real,-C1.imag); 39 } 40 complex operator*(const complex&C1,const complex&C2)//乘的实现 41 { 42 return complex(C1. realC2.real-C1.imagC2.imag,C1.realC2.imag+C1.imagC2.real); 43 } 44 complex operator/(const complex&C1,const complex&C2)//除的实现 45 { 46 return 47 complex((C1.realC2.real+C1.imag+C2.imag)/(C2.realC2.real+C2.imag*C2.imag), 48 (C1. imagC2.real-C1.realC2.imag)/(C2.realC2.real+C2.imagC2.imag)); 49 } 50 complex&operator++(complex&C1)//前置++的实现 51 { 52 cout<<"前置++"<<endl; 53 C1. real+=1; 54 C1. imag+=1; 55 return C1; 56 } 57 complex operator++(complex&C1,int)//后置++的实现,体会和前置++的区别 58 { 59 cout<<"后置++"<<endl; 60 complex ctemp=C1; 61 ++C1; 62 return ctemp; 63 } <———————————-文件名:example908.cpp———————————————-> 64 #include"complex.h" 65 int main() 66 { 67 complex cx1(1. 0,2.0),cx2(3.0,4.0),cxRes; 68 cxRes=cx1-cx2;//相当于cx1.operator-(cx2) 69 cxRes. disp(); 70 cxRes=-cx1;//相当于cx1.operator-() 71 cxRes. disp(); 72 cxRes=cx1+cx2;//相当于cx1.operator+(cx2) 73 cxRes. disp(); 74 cxRes=cx1cx2;//相当于cx1.operator(cx2) 75 cxRes. disp(); 76 cxRes=cx1/cx2;//相当于cx1.operator/(cx2) 77 cxRes. disp(); 78 complex cx3(1. 0,1.0),cx4(5.0,5.0); 79 cxRes=++cx3;//相当于cx3.operator++() 80 cxRes. disp(); 81 cx3. disp(); 82 cxRes=cx4++;//相当于cx4.operator++(0) 83 cxRes. disp(); 84 cx4. disp(); 85 return 0; 86 }

    输出结果如下所示。


    -2+i*-2 -1+i*-2 4+i*6 -5+i*10 0.36+i*0.08 前置++ 2+i*2 2+i*2 后置++ 前置++ 5+i*5 6+i*6

    【代码解析】代码9.8和代码9.7的输出结果完全一致,以友元函数形式重载运算符与以成员函数形式重载运算符相比,最大的不同在于参数的个数(见代码第28~63行)。对双目运算符而言“对象1、运算符、对象2”解释为“operator运算符(对象1,对象2)”,而对单目运算符来说,前置运算符“运算符、对象”解释为“operator运算符(对象)”,而后置运算符解释为“operator、运算符、(对象,0)”,但不论怎样重载运算符,运算符的结合性和优先级并不会改变。