一、重载运算符的限制
1,不能被重载的运算符: * :: ?: sizeof
2,重载运算符函数可以对运算符做出新的解释,定义用户所需要的各种操作,运算符重载后,原有的基本语义不变
1)不改变运算符的优先级
2)不改变运算符的结合性
3)不改变运算符所需要的操作数
注:重载运算符只是扩展了运算符的应用范围,只是重新定义含义,但不能创建新的运算符
二、运算符的语法形式
1,运算符函数是一种特殊的成员函数或友元函数
格式: 类型 类名::operatpr op(参数表)
{
//相对于该类定义的操作
}
注:类型—函数的返回值类型
类名—要重载该运算符的类
op—要重载的运算符
参数表—列出该运算符所需要的操作数
2,例如:classCalculator
{
public:
void operator ++();
private:
unsigned int value;
};
void class::operator++()
{
//函数体
}
三、用成员函数或友元函数重载运算符
1,一元运算符:一元运算符不论前置还是后置,都要求有一个操作数 object op或op object
1)当重载为成员函数时,编译器解释为object.operator op()
注:函数所需要的操作数由对象object通过this指针隐含传递,所以参数表为空
2)当重载为友元函数时,
Operator op(object)
2,二元运算符
任何二元运算符都要求有左右操作数,objectL op objectR
1)当重载为成员函数时, object.Operatorop(objectR)
2)当重载为友元函数时,operatorop(objectL,objectR)
左右操作数都由参数传递
3,用成员函数重载运算符
1)当一元运算符的操作数,或者二元运算符的左操作数是该类的一个对象时,重载运算符函数一般定义为成员函数
例如:重载+
class TriCoor
{
public:
TriCoor operator+(TriCoort);
private:
Int x,y,z;
};
TriCoor::TriCoor (int mx,int my,int mz)
{ x=mx;
y=my;
z=mz;
}
TriCoor::TriCoor operator +(TriCoor t)
{
triCoor temp;
temp.x=x+t.x;
temp.y=y+t.y;
temp.z=z+t.z;
return temp;
}
注:重载运算符+的成员函数参数表只有一个参数,另一个操作数由this指针隐含传递
语句:temp.x=x+t.x;相当于temp.x=this->x+t.x;其中,this是操作的左操作数
4,用友元函数重载运算符
friend Complex operator +(Complex,Complex);
两个操作数完成
三、几个典型运算符的重载
<一>重载++与- -
1,前置自增表达式
++Aobject
1)若用成员函数重载,则编译器解释为
Aobject operator ++()
对应的函数原型为
A&A::operator ++()
注:此时括号中没有参数
2)若用友元函数重载,则编译器解释为:
friend A&operator ++(A&);
注:友元函数必须要带参数
2,后置自增表达式
Aobject ++
成员函数重载的解释为
Aobject.operator++(0)
对应的函数原型为;A&A::operator ++(int);
注:此时括号内是有参数的,但是这个参数只是为了和前置++进行区分,并没有实际作用
2)友元函数重载的解释为
operater ++(Aobject,0)
对应的函数原型为:friend A& operator ++(A&,int);
注:第一个操作数是对象,要进行操作,但是第二个对象只是为了区分前置,不起任何作用
<二>重载- -
重载自减运算符与重载自加运算符格式相同
<三>重载赋值运算符=
赋值运算符重载用于对象的数据的复制,只能用于成员函数重载,重载函数原型为:
类名&类名::operator = (类名);
注:括号中的类名是指的要赋值的对象
例:
#include<bits/stdc++.h>
using namespace std;
class Name
{
public:
Name (char *pN="\0");//构造函数
Name (const Name &);//复制构造函数
Name &operator =(Name);//重载赋值号
~Name();
protected:
char *pName;
int size;
};
Name :: Name(char *pN)
{
cout<<"Constructing "<<pN<<endl;
size =strlen(pN);
pName=new char[size+1];
if(pName!=0)strcpy_s(pName,size+1,pN);
}
Name ::Name(const Name &Obj)
{
cout<<"Copying "<<Obj.Pname<<"into itsown block\n";
size=Obj.size;
pName=new char[size+1];
if(pName!=0)strcpy_s(pName,size+1,Obj.pName);
}
Name &Name operator =(Name Obj)
{
delete []pName;
size=Obj.size;
pName=new char[size +1];
if(pName!=0)strcpy_s(pName,size+1,Obj.pName);
}
int main()
{
Name Obj1("zhangsan");
Name Obj2=Obj1;
Name Obj3("noname");
Obj3=Obj2=Obj1;
}
注:1,重载赋值运算符函数与复制构造函数的实现十分相似,但是不同的是,重载函数返回*this
2,复制构造函数在实现成员的复制时,用于对象的初始化,重载运算符用于程序运行时修改对象的数据
3,重载赋值运算符的实现必须是成员函数
<四>重载[ ],( )
1,重载下标运算符[ ]
[ ]是二元运算符,用于访问数据对象的元素
格式 对象[表达式]
例如:类X有重载函数 int &X::operator [ ] (int)
其中,x是X的对象,则调用的函数表达式x[k]的意思就是调用x中的第k个元素
被解释为: x.operator[ ](k)
2,重载函数调用运算符( )
( )是一个二元运算符,
格式: 对象 (表达式表)
其中,表达式表可以为空
3,重载输入输出流
函数名:
输出流: operator<<(参数表)
输入流:operator>>(参数表)
参数表:固定,两个参数均用引用&
输出流: 必须是两个参数:对输出流ostream&和 对象
第一个操作数cout,定义在文件iostream中,是标准类类型ostream的对象的引用 如:ostream& cout,const Point& p
输入流:必须是两个参数:对输入流ostream& 和 对象
第一个操作数是cin,定义在文件iostream,实际上是标准类类型istream的对象的引用
如:instream& cin,const Point& p
函数调用:
输出流: 显式调用:cout<<对象
隐式调用: operator<<(cout,对象)
输入流:显式调用:cin>>对象
隐式调用: operator>>(cin,对象)
返回类型:返回类型固定 + 使用返回函数引用(满足连续输出)
输出流: 返回ostream&
如:ostream& operator<<(ostream&cout,const Point& p)
输入流:返回:istream&
如:istream& operator>>(istream& cin,Point& p)
注:输入输出操作符的重载必须使用友元函数,因为成员函数要求是有对象调用,则第一个参数必须是类的对象,但是<<和>>第一个参数是流的对象引用。故,不能使用成员函数
四、学习心得
1,一般的运算符只能在一些数据之间进行运算,重载运算符解决了对象之间的运算,、
2,不管是成员函数重载还是友元函数重载,运算符的使用方法都相同,但是由于他们传递参数的方法不同,因此导致实现的代码不同,应用场合也不同。