运算符重载的概念和语法
重载,就是赋予新的含义,运算符重载和函数重载类似,同一个运算符可以有不同的功能。
运算符重载的方式就是定义一个函数,在函数体内实现想要的功能,当用到该运算符时,编译器就会自动调用这个函数。也就是说,运算符重载就是通过函数定义实现的,它本质上是函数重载。
返回值类型 operator 运算符名称(形参列表){
//TODO;
}
operator是关键字,专门用于定义重载运算符的函数。
重载运算符的规则:
1.并不是所有运算符都可以重载;
长度运算符(sizeof)、条件运算符(: ?)、成员选择符(.)、对象选择符(.*)、域解析符(::)不能被重载。
2.重载不能改变运算符的优先级和结合性。
3.重载不会改变运算符的用法。例如"+"号总是出现在两个操作数之间。
4.重载运算符的函数不能有默认的参数,否则就改变了运算符操作数的个数,显然是错误的。
例:
1."+"和"-" 运算符的重载:
class Point { private: int x; public: Point(int x1) { x=x1;} friend ostream& operator<<(ostream& cout,const Point& p);//使用友元函数重载<<输出运算符 friend istream& operator>>(istream& cin,Point& p);//使用友元函数重载>>输出运算符 }; ostream& operator<<(ostream& cout,const Point& p) { cout<<p.x<<endl; return cout; } istream& operator>>(istream& cin,Point& p) { cin>>p.x; return cin; }
2.下标运算符"[ ]"的重载:
class Point { private: int x[5]; public: Point() { for (int i=0;i<5;i++) { x[i]=i; } } int& operator[](int y); }; int& Point::operator[](int y) { static int t=0; if (y<5) { return x[y]; } else { cout<<"下标出界"; return t; } }
调用:
Point a; for (int i=0;i<10;i++) { cout<<a[i]<<endl;//无论i下标是否越界,每当使用a[i]时,都会调用[]的重载 } a[0]=10;
3.输入输出符">>" "<<"的重载:
class Point { private: int x; public: Point(int x1) { x=x1;} friend ostream& operator<<(ostream& cout,const Point& p);//使用友元函数重载<<输出运算符 friend istream& operator>>(istream& cin,Point& p);//使用友元函数重载>>输出运算符 }; ostream& operator<<(ostream& cout,const Point& p) { cout<<p.x<<endl; return cout; } istream& operator>>(istream& cin,Point& p) { cin>>p.x; return cin; }
调用:
Point a(1); Point b(2); cin>>a>>b; cout<<a<<b<<endl;
重载=(赋值运算符)
对象之间也可以相互赋值,对象之间的赋值是将成员变量依次拷贝,而不是将整个对象的内存按位拷贝。一般情况下,默认的”=”就能满足我们的需求,但是当一个类中包含指针类型的成员变量时,可能会带来问题。
1、单目运算符的重载:
重载运算符函数名:operator@(参数表)
隐式调用形式:obj1@ 或 @obj1
显式调用形式:
成员函数:
obj1.operator@( )//前缀
obj1.operator@(0)//后缀
友元函数:
operator@(OBJ obj)//前缀
operator@(OBJ obj,int x)//后缀
执行时,隐式调用形式和显式调用形式都会调用函数operator@()
2、双目运算符的重载:
重载运算符函数名:operator@(参数表)
隐式调用形式:obj1+obj2
显式调用形式:obj1.operator+(OBJ obj2)---成员函数
operator+(OBJ obj1,OBJ obj2)---友元函数
执行时,隐式调用形式和显式调用形式都会调用函数operator+()