运算符重载
C++为预定义的数据类型提供了丰富的运算符集,以简单的符号定义运算,当然我们自己也可以重新定义运算符我们想要的运算形式。这就要运算符重载了。
1. 重载运算符的限制:
可以重载的运算符有:
+ - * / % ^ % | ~ ! = 《 》 += -= *= /= %= ^= &= |= << >> <<= >>= == != <= >= && || ++ – ->* ’ -> [] () new delete
一下运算符不能被重载:
.(成员访问运算符) .*(成员指针运算符) ::(作用域符号) ?:(条件运算符) sizeof
重载后基本语义不能变:
不能变运算符的优先级
不能变运算符的结合性
不能变运算符的所需操作数
不能创建新的运算符,只能重载系统预定义的运算符。
2.重载语法形式:
类型 类名::operator op(参数表) //op处输入要重载的运算符,类型是函数的返回类型,类名是要重载该运算符的类,函数名是“operatro op”,operator 是一个关键词,参数表传入操作数
{
//定义操作
}
class calculator { public: double value ; void operator ++(); } void calculator :: operator ++() { if (value<65535)++value; else {cout <<"\n data flow!"<<endl;abort();} 12 } void main () { calcualtor counter; ++counter; //counter.operator ++(); 两种调用方法 }
3.用成员函数和友元函数来重载运算符:
(1)成员函数
重载一元运算符:需要一个操作数,重载函数的操作数由隐含的this指针传递,所以参数列表为空。
重载二元运算符:需要两个操作数,重载函数的左操作数由隐含的this指针传递,所以参数列表只有一个操作数。
class tricoor { double x,y,z; publice : tricoor ( int mx=0,int my=0,int mz=0):x(mx),y(my),z(mz){}; tricoor & operator ++(); tricoor & operator =(tricoor t); } tricoor & tricoor :: operator ++() { x++; y++; z++; return *this; } tricoor & tricoor :: operator =(tricoor t) /传入的参数就是调用时的右操作数。 { x=t.x; y=t.y; z=t.z; rerurn *this; //*this 是左操作数,是调用该函数的对象。这里是返回类类型的引用,这样就既符合运算符的原本语义,又减少了函数返回时对匿名对数据的复制开销。 } void main() { tricoor a(1,2,3),b,c,d; c=a+b+c; }
(2)友元函数
当运算符的左右操作数类型不同,用成员函数来重载就会遇上问题,例如:
class complex { double real,image; publice : complex (int a){real=a;image=0;}; complex (int a,int b){real=a;image=b;}; complex operator +(complex a) { real+=a.real; image+=a.image; }; } void main() { complex z(1,2), k(2,3); z=z+25; //这样右操作数25就会传进形参,根据构造函数构建一个复数25,建立临时对象执行函数,是合理的 z=25+z; //当解释为系统预定义的版本,但是z无法被转换成基本数据类型;当解释为重载版本时,25.operator+() 由于25这个整型数据无法驱动函数,也是失败的。 }
但是,如果用友元函数,传入的参数都是平等的,就不会有这种问题了。
重载一元运算符:传入一个参数;
重载二元运算符:传入两个参数。
例如:
class complex { double real,image; publice : complex (int a){real=a;image=0;}; complex (int a,int b){real=a;image=b;}; friend complex operator +(const complex &c1,const complex &c2) //加上const 是为了限制对实参只读。 { double r=c1.real+c2.real; double i=c1.image+c2.image; return complex (r,i); //显式调用构造函数,返回一个创建出来的匿名对象 }; }; void main () { complex c1(1,2),c2(5,6),c3; c3=c1+c2; }
(3)当一个运算符的操作需要修改类对象的状态时,应该以成员函数重载,例如,左值操作数的运算符(=,*=,++等)应该用成员函数来重载。如果要用友元函数的话,那么就要使用引用参数来修改对象。
C++中不能用友元函数重载的运算符有:
= () 【】 ->
未完待续…