重载运算符学习心得

运算符重载

  运算符重载的限制

有几种不能能重载运算符

,:: .* ?: sizeof

 

重载运算符函数 可以重新定义运算符函数,但是原有的基本语义不变:

1.   不改变运算符的优先级

2.   不改变运算符的结合性

3.   不改变运算符所需要的操作数

4.   不能创建新的运算符

5.   运算符函数可以重载为成员函数或者友元函数

 

语法形式

类型 类名::operator op(参数表)

{//结构体

}

类型 函数的返回类型

类名 要重载该运算符的类

Op 表示要重载的运算符

函数名 operator op 由关键字operator和被重载的运算符op组成。

参数表列出该运算符所需要的操作数。

 

有两个运算符系统提供默认版本

赋值运算符“=” 系统默认重载为对象数据成员的复制。

地址运算符“&”系统默认重载为返回任何对象类的地址。

 

 一元运算符

Object op op object

重载运算符函数 解释为

Object.operator op()

操作数由对象object通过this指针隐含传递。

重载为友元函数 解释为

Operator opobject

操作数由参数表的参数object提供

二元运算符

Objectl op objectr

重载为成员函数 解释为

Objectl.operator op (objectr)

左操作数由objectl通过this指针传递,右操作数由参数objectr传递。

重载为友元函数时 解释为

Operator opobjectlobjectr

左右操作数都由参数传递。

 用成员函数重载运算符

成员运算符函数的类型在类的内声明格式如下:

Class x

{//….

返回类型 Opeator 运算符(形参表);

//…

};

在类外定义成员函数的格式如下:

返回类型 x::operator运算符(形参表)

{函数体}

对于双目运算符而言,成员运算符函数的形参表中仅有一种一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它时通过this指针隐含的传递给函数的。

#include <iostream.h>//复数的加减

class Complex            //重载+运算符

{

public:

Complex( )                                           {real=0,imag=0;}

Complex(double r,double i)               {real=r; imag=i;}

Complex operator + (Complex &c2); //重载元算符+

void display( );

private:

 double real;

 double imag;

};

 ComplexComplex:: operator + (Complex &c2) {

return Complex(real+c2.real, imag+c2.imag);}

void Complex::display( ){

cout<<"("<<real<<","<<imag<<"i)"<<endl;}

int main( ){

Complex c1(3,4),c2(5,-10),c3;

c3=c1+c2;

cout<<"c1=";c1.display( );

cout<<"c2=";c2.display( );

cout<<"c1+c2 =";c3.display();

return 0;

}

  在成员函数中分为显示调用和隐式调用

    一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@ 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aabb是类X的两个对象,则以下两种函数调用方法是等价的:

    aa @bb;                      // 隐式调用

    aa.operator@(bb);     // 显式调用

单目运算符重载为成员函数

对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。

有一个Time类,包含数据成员minute()sec(),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。

class Time

{

public:

          Time(){minute=0;sec=0;}

          Time(intm,int s):minute(m),sec(s){ }// 分 秒

          Timeoperator++( );     //声明前置自增运算符“++”重载函数

          Timeoperator++(int);   //声明后置自增运算符“++”重载函数

private:

          intminute;

          intsec;

};

Time Time∷operator++( )    //定义前置自增运算符“++”重载函数

{

     if(++sec>=60)    {   

          sec-=60;         //60秒进1分钟

          ++minute;

     }

     return*this;          //返回当前对象值

}

Time Time∷operator++(int)  //定义后置自增运算符“++”重载函数

{

     Timetemp(*this);

     sec++;

     if(sec>=60) {

          sec-=60;

          ++minute;

     }

     returntemp;         //返回的是自加前的对象

}

    一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的:

    @aa;                      // 隐式调用

   aa.operator@();    // 显式调用

    成员运算符函数operator @所需的一个操作数由对象aa通过this指针隐含地传递。因此,在它的参数表中没有参数。

当运算符左右操作的类型不同时,这是则使用友元函数进行重载。

class   Complex

{     int   Real ; int    Imag ;

   public :

       Complex ( int a ) { Real = a ;   Imag = 0 ; }    

       Complex ( int  a  ,int  b ) { Real = a ;   Imag = b ; }

       Complex operator + ( Complex ) ;

  …...

};  

int   f ( )

{Complex  z ( 2 , 3 ) ,   k ( 3 , 4 ) ;

   z = z + 27 ;//所对应的形式正确

   z = 27 + z ;//所对应的形式错误

      …...

}

Ø在第一个参数需要隐式转换的情形下,使用友元函数重载

    运算符是正确的选择

Ø 友元函数没有 this 指针,所需操作数都必须在参数表显式

    声明,很容易实现类型的隐式转换

Ø C++中不能用友元函数重载的运算符有

  =    ()   []    >

成员函数与友元运算符函数的比较

(1) 成员运算符函数比友元运算符函数少带一个参数(后置的++--需要增加一个形参)。

(2)  双目运算符一般可以被重载为友元运算符函数或成员运算符函数,当操作数类型不相同时,必须使用友元函数。

  四 几个经典运算符重载

>>数学类中几个常用运算符重载的特点和应用

                        A  Aobject

运算符 ++ - - 有两种方式:

前置方式        ++Aobject --Aobject

  成员函数 重载  A :: Aoperator++ () ;  

                            解释为:    Aobject. operator ++( ) ;

    友元函数  重载   friendA operator++ (A &) ;

                        解释为: operator++( Aobject ) ;   

后置方式

成员函数  重载 A::A operator++ (int) ;

                        解释为: Aobject. operator ++( 0 ) ;

友元函数  重载:  friendA operator++ (A &, int) ;                                 解释为: operator++(Aobject, 0)

例如:重载++的应用

#include<iostream>

using namespace std;

class  Increase

{ public :

     Increase () { value=0; }

     void  display( ) const{ cout<<value<<'\n'; } ;

    Increase  operator ++ ( ) ;           //前置

    Increase  operator ++ ( int ) ;          //后置

  private:   unsigned value ;

};

Increase Increase :: operator ++ ( )   

  { value ++;   return *this ; }   

Increase Increase :: operator ++ ( int )    

 { Increase  temp;  temp.value = value ++ ;  return  temp; }

 

int main( )

  {Increase   a ,  b , n ;    int  i;

     for ( i = 0; i < 10 ; i ++ )  a = n ++ ;

     cout<<"n= " ; n.display( ) ; cout <<"a= " ;   a.display( ) ;

     for ( i = 0; i < 10 ; i ++ )  b = ++ n ;

     cout<< "n= " ;n.display( ) ;cout << "b= " ;   b.display();

重载复制运算符

用于对象数据的复制

Operator=必须重载为成员函数

重载函数原型为:

类名 & 类名::operator=(类名);

#include<iostream>

#include<cstring>

using namespace std;

class  Name

{ public :

     Name (char  *pN ) ;

     Name( constName & ) ;          //复制构造函数

     Name&operator=( const Name& ) ;     // 重载赋值运算符

     ~ Name() ;//析构函数

  protected :

     char  *pName ;

     int size ;

} ;

int main()

{ Name Obj1( "ZhangSan" ) ;

   Name Obj2 =Obj1 ;       // 调用复制构造函数

   Name Obj3("NoName" ) ;

   Obj3 = Obj2 =Obj1 ;     // 调用重载赋值运算符函数

}

Name::Name ( char *pN )

 { cout<<" Constructing " << pN << endl ;

    pName = newchar[ strlen( pN ) + 1 ] ;

    if( pName !=0 ) strcpy( pName,pN ) ;

    size =strlen( pN ) ;

 }

Name::Name( const Name & Obj )   //复制构造函数

{ cout << " Copying " <<Obj.pName << " into its own block\n";

   pName = new char[strlen( Obj.pName ) + 1 ] ;

   if ( pName !=0 ) strcpy( pName, Obj.pName ) ;

   size =Obj.size;

}

Name & Name::operator= ( const Name & Obj )    // 重载赋值运算符

{ delete []pName ;

   pName = newchar[ strlen( Obj.pName ) + 1 ] ;//获取长度

   if ( pName !=0 ) strcpy( pName , Obj.pName ) ;

   size =Obj.size ;

   return *this;

}

Name::~ Name()

{ cout << " Destructing " <<pName << endl ;

   delete  []pName ;

   size = 0;

}

重载运算符【】和()

运算符【】和()时二元运算符

【】和()只能用成员函数重载,不能使用友元函数重载

1.    重载下标运算符【】

【】运算符用于访问数据对象的元素

重载格式             类型  ::operator[]  ( 类型 )

x 是类 X 的一个对象,则表达式

                                x [ y ]

                            可被解释为

                                x . operator [ ]( y )

#include<iostream>

using namespacestd;

class  vector

{ public :

       vector ( int  n ) {  v = new  int [ n ] ; size = n ; }

       ~ vector ( )  { delete [ ] v ; size = 0 ; }

       int & operator [ ] ( int  i ) {  return  v [ i ] ; }

   private :      

       int * v ;       int size ;

};

int main ( )

{  vector a ( 5 ) ;

    a [ 2 ] = 12 ;     

    cout << a [ 2 ] << endl ;

}

2.    重载函数调用运算符

()运算符用于函数调用

                                                                  

重载格式类型  :: operator()  ( 参数表  )

x 是类 X 的一个对象,则表达式     x ( arg1, arg2, )可被解释为x . operator () (arg1, arg2, )

#include <iostream>

using namespace std ;

class  F

  { public: 

       double  operator ( )  ( double x , double  y ) ;

  } ;

double  F ::operator ( )  ( double  x , double  y )

   { return   x * x + y * y ; }

int main ( )                                                       

{ F  f  ;

   cout <<f ( 5.2 , 2.5 ) << endl ;

}

 

重载流插入和流提取运算符

Ø istream ostream C++的预定义流类

Ø cin istream 的对象,cout ostream 的对象

Ø 运算符 << ostream 重载为插入操作,用于输出基本类型数据

Ø 运算符 >> istream 重载为提取操作,用于输入基本类型数据

Ø 用友元函数重载 << >> ,输出和输入用户自定义的数据类型

重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)

     定义输出运算符“<<”重载函数的一般格式如下:

   ostream& operator<<(ostream& outclass_name& obj)

    {

         out<<obj.item1;

         out<<obj.item2;

         .. .

         out<<obj.itemn;

         return out;

    }

重载输入运算符“>>” (只能被重载成友元函数)

        定义输入运算符函数 “>>”重载函数的一般格式如下:

   istream& operator>>(istream& inclass_name& obj)

    {

           in>>obj.item1;

           in>>obj.item2;

           . . .

           in>>obj.itemn;

           return in;

    }

#include<iostream>

#include<cstdlib>

using namespace std;

class vector

{ public :

    vector( int size =1 ) ;      ~vector() ;

    int & operator[] ( int i ) ;

    friend ostream & operator << ( ostream & output , vector& ) ;

    friend istream & operator >> ( istream & input, vector& ) ;

 private : 

    int * v ;     int len ;

};

int main(){

  int k ;    cout <<"Input the length of vector A :\n" ;     cin >> k ;

 vector A( k ) ;    cout <<"Input the elements of vector A :\n" ;   

  cin >> A ;          cout<< "Output the elements of vector A :\n" ;

 cout << A ;

}

vector::vector( int size )

{ if (size <= 0 || size > 100 )

    {cout << "The size of " << size << " is null!\n" ; exit( 0 ) ;  }

   v= new int[ size ] ;  len = size ;

}

vector :: ~vector() { delete[] v ;  len = 0 ; }

int & vector :: operator [] (int i )    

{ if( i >=0 && i < len )  return v[ i ] ;

 cout << "The subscript " << i << " isoutside !\n" ;  exit( 0 ) ;

}

ostream & operator << (ostream & output, vector & ary )

{ for(int i = 0 ; i < ary.len ; i ++)  output << ary[ i ] <<"  " ;

  output << endl ;

  return output ;

}

istream & operator >> (istream & input, vector & ary )                                                          

{ for( int i = 0 ; i < ary.len ; i ++)  input >> ary[ i ] ;

  return  input ;

}

 

猜你喜欢

转载自blog.csdn.net/qq_41549459/article/details/80456387