1.运算符重载规则
在c++中,操作符和函数时等价的,统一的。因此,运算符也可以重载,虽然系统已经预定了一些操作符的功能,但毕竟应用有所限制,不能灵活得解决各种问题,而运算符重载可以赋予已有的运算符多重含义。通过重新定义运算符,使它能够用于特定类的对象执行特定的功能,使得c++具有很强的可拓展性。
c++中可重载运算符有一下几种:
算术运算符:+,-,*,/,%,++,--; 位操作运算符:&,|,~,^,<<,>> 逻辑运算符:!,&&,||; 比较运算符:<,>,>=,<=,==,!=; 赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=; 其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
有五个不可重载运算符:
. 成员运算符 .* 指向成员的指针 :: 作用域运算符 ?: 条件运算符 sizeof 类型长度运算符
2.以成员函数形式重载运算符
成员函数形式的运算符声明与成员函数类似,首先应当类定义中声明该运算符,声明的具体形式如下所示:
返回类型 operator 运算符(参数列表) 既可以在类定义的同时定义运算符函数使其成为inline函数,也可以在类定义之外定义运算符函数,但是要使用作用域限定符“::”,类外定义的基本格式如下所示: 返回类型 类名::operator 运算符(参数列表)
以下代码定义了复数类,并重载了其四则运算。
1 /***********************complex.h******************/ 2 #include <iostream.h> 3 using namespace std; 4 class complex 5 { 6 private: 7 double real,imag; 8 public: 9 complex(double r = 0.0,double i = 0.0) 10 { 11 real = r; 12 imag = i; 13 } 14 complex operator + (const complex &); 15 complex operator - (const complex &); 16 complex operator - (); //取反运算符 17 complex operator * (const complex &); 18 complex operator / (const complex &); 19 complex operator ++ (); //前置++ 20 complex operator ++ (int) ; //后置++ 21 void disp() 22 { 23 cout<<real<<" + "<<"i*"<<imag<<endl; 24 } 25 }; 26 27 /*******************complex.cpp*****************/ 28 #include "complex.h" 29 complex complex::operator + (const complex& CC) 30 { 31 return complex(real + CC.real,imag + CC.imag); 32 } 33 34 complex complex::operator - (const complex& CC) 35 { 36 return complex(real - CC.real,imag - CC.imag); 37 } 38 39 complex complex::operator - () 40 { 41 return complex(-real ,-imag; 42 } 43 44 complex complex::operator * (const complex& CC) 45 { 46 return complex(real*CC.real - imag*CC.imag , real*CC.imag + imag*CC.real); 47 } 48 49 complex complex::operator / (const complex& CC) 50 { 51 return complex((real*CC.real + imag + CC.imag)/(CC.real*CC.real + CC.imag*CC.imag),(imag*CC.real - real*CC.imag)/(CC.real*CC.real + CC.imag*C.imag)); 52 } 53 54 complex& complex::operator ++() 55 { 56 cout<<"前置++"<<endl; 57 real +=1; 58 imag +=1; 59 returun (*this); 60 } 61 62 complex& complex::operator ++(int) 63 { 64 cout<<"后置++"<<endl; 65 complex ctemp = *this; 66 ++(*this); 67 return ctemp; 68 } 69 70 71 /*********************main.c*****************/ 72 #include "complex.h" 73 int main() 74 { 75 complex cx1(1.0,2.0),cx2(3.0,4.0),cxRes; 76 cxRes = cx1 - cx2; 77 cxRes.disp(); 78 79 cxRes = -cx1; 80 cxRes.disp(); 81 82 cxRes = cx1 + cx2; 83 cxRes.disp(); 84 85 cxRes = cx1 * cx2; 86 cxRes.disp(); 87 88 cxRes = cx1 / cx2; 89 cxRes.disp(); 90 91 complex cx3(1.0,1.0),cx4(5.0,5.0); 92 cxRes = ++cx3; 93 cxRes.disp(); 94 cx3.disp(); 95 96 cxRes = cx4++; 97 cxRes.disp(); 98 cx4.disp(); 99 100 return 0; 101 }
输出结果为:
1 -2 + i*-2 2 -1 + i*-2 3 4 + i*6 4 -5 + i*10 5 0.36 + i*0.08 6 前置++ 7 2 + i*2 8 2 + i*2 9 后置++ 10 前置++ 11 5 + i*5 12 6 + i*6
3.以友元函数形式重载运算符
用成员函数重载双目运算符时,左操作数无需参数输入,而是通过隐含的this指针传入,这种做法效率比较高。此外,操作符还可以重载为友元函数形式,这样没有隐含的参数this指针。对双目运算符,友元函数有两个参数,对单目运算符,友元函数有一个参数,声明格式如下:
friend 返回类型 operator 运算符(参数表)
4.友元函数形式和成员函数形式的比较
对于绝大多数可重载操作符,两种重载形式都是允许的,但是对于下述运算符,只能使用成员函数形式:
[] 下标运算符 = 赋值运算符 () 函数调用运算符 -> 用指针访问对象成员
错误使用例子:
用两种形式编译如下代码:
complex c1(1.0,2.0),cRes; cRes = 5 + c1;
使用成员函数形式会报错,因为编译器将它解释为
cRes = 5.operator + (c1);
而友元函数形式解释为
cRes = operator +(5,c1); 这时编译器会根据合适的构造函数将“5”转换为complex临时变量,完成参数匹配,实现加法操作。