运算符重载总结

一、重载运算符的限制

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,不管是成员函数重载还是友元函数重载,运算符的使用方法都相同,但是由于他们传递参数的方法不同,因此导致实现的代码不同,应用场合也不同。

 

 


猜你喜欢

转载自blog.csdn.net/pxl20171799/article/details/80470615