浅谈C++运算符重载

浅谈C++运算符重载

一、友元函数重载

当一元运算符的操作数,或者二元运算符的左操作数是类的对象时,定义重载算符函数为成员函数。

注意:= () [] 不能用友元重载!

友元函数重载运算符常用于运算符的左右操作数类型不同的情况

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 ;		//ok!
   z = 27 + z ;		//no!!!
      …...
}
#include<iostream.h>
class Complex
{ public:
      Complex( double r =0, double i =0 ) { Real = r ;   Image = i ; }
      Complex(int a) { Real = a ;  Image = 0 ; } 
      void print() const ;
      friend Complex operator+ ( const Complex & c1, const Complex & c2 ) ;
      friend Complex operator- ( const Complex & c1, const Complex & c2 ) ;
      friend Complex operator- ( const Complex & c ) ;
  private:  
      double  Real, Image ;
};
Complex operator + ( const Complex & c1, const Complex & c2 )
  { double r = c1.Real + c2.Real ;  double i = c1.Image+c2.Image ;
     return Complex ( r,  i ) ;
  }
Complex operator - ( const Complex & c1, const Complex & c2 )
  { double r = c1.Real - c2.Real ;  double i = c1.Image - c2.Image ;
     return Complex ( r,  i ) ;
  }
Complex operator- ( const Complex & c )
  { return Complex ( -c.Real, - c.Image ) ; }
void Complex :: print() const
  { cout << '(' << Real << " , " << Image << ')' << endl ; }

友元函数使用传值参数,对 参数 的所有修改都无法传到函数体外,不会影响被调用的对象!

重载为友元函数,如果一个运算符的操作要修改类的对象的状态,应该使用引用参数。

1.若一元运算符的操作需要修改类对象状态时,应该用成员函数重载
2.需要左值操作数的运算符(如 ++,–),若重载为友元函数时要用引用参数
3.C++不能用友元重载的运算符: = () [] →

4.如果运算符的操作数(尤其是第一个操作数)希望有隐式转换,则必须用友元函数重载

二、几个典型运算符重载

1.自增自减

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

前置方式: ++Aobject --Aobject

一元 成员函数 重载 A :: A operator++ () ;
解释为: Aobject . operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;

后置方式: Aobject ++ Aobject –

二元 成员函数 重载 A :: A operator++ (int) ;
解释为: Aobject . operator ++( 0 ) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject, 0)

前置(空参数)

后置(伪参数)

友元函数重载
#include<iostream>
using namespace std;
class  Increase
{ public :
     Increase ( ) { value=0; }
     void  display( )  const { cout<<value<<'\n'; } ;
     friend Increase  operator ++ ( Increase & ) ; 	 		// 前置,使用引用
     friend Increase  operator ++ ( Increase &, int ) ;	 	// 后置,使用引用
  private:   unsigned  value ;
};
Increase  operator ++ ( Increase & a )
  { a.value ++ ;   return a ; }	
Increase  operator ++ ( Increase & a, int )
 { Increase  temp(a);   a.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( ) ;
 }

用成员函数重载自增/减
#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( ) ;
 }

重载自增/减运算符 参数不写时 前增

2.赋值 =

= 必须重载为成员函数

重载函数原型为:

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

#include<iostream>
#include<cstring>
using namespace std;
class  Name
{ public :
     Name ( char  *pN ) ;
     Name( const Name & ) ;		    //复制构造函数 
     Name& operator=( const Name& ) ;	    // 重载赋值运算符
     ~ Name() ;
  protected : 
     char  *pName ;
     int size ;
} ;
Name::Name ( char  *pN )
 { cout <<" Constructing " << pN << endl ;
    pName = new char[ 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 = new char[ 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;
}
int main()
{ Name Obj1( "ZhangSan" ) ;
   Name Obj2 = Obj1 ;		// 调用复制构造函数 
   Name Obj3( "NoName" ) ;
   Obj3 = Obj2 = Obj1 ;		// 调用重载赋值运算符函数 
}
3.[]和()

只能用成员函数重载,不能用友元函数重载

1)下标运算符 []

用于访问数据对象的元素

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

类型:右操作数为符合原语义,用 int

即——类型 类 :: operator[] (int ) ;

#include<iostream>
using namespace std;
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()  ( 参数表  ) ;
//用重载()运算符实现数学函数的抽象
#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 ;
}
4.流插入和流提取

使用友元重载!

ostream & operator << ( ostream & 输出的别名, 类名 & 对象名 )
{ 
   自定义的内容
   return 输出的别名 ;
}
istream & operator >> ( istream & 输入的别名, 类名 & 对象名 )	
{ 
   自定义的内容
   return 输入的别名 ;
}

//例:为vector类重载流插入运算符和提取运算符

#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 ;
};
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 << " is outside !\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 ;
}
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 ;
}

三、(类)类型转换函数

数据类型转换在程序编译时或在程序运行实现
基本类型 ←→ 基本类型
基本类型 ←→ 类类型
类类型 ←→ 类类型

1)类类型转换

通过构造函数实现 基本类型 ←→ 类类型 的 类类型转换

class  X
{ // ……
  public :
      X ( int ) ;						 //int 转换为类类型
      X ( const  char * , int = 0 ) ;	//字符串转换为类类型
};
void  f ( X  arg ) ;
X  a = X( 1 ) ;		// a = 1
   X  b = "Jessie" ;		// b = X ( "Jessie" , 0 )
   a = 2 ;			// a = X ( 2 )  隐式调用构造函数 X ( int ) 
   f ( 3 ) ;			// f ( X ( 3 ) ) 参数为整型,隐式调用构造函数,实现类型转换
2)类型转换函数

带参数的构造函数不能把一个类类型转换成基本类型

形式:

X :: operator  T ( )
		{  ……
	  	   return   T 类型的对象  
		}

功能:将类型 X 的对象转换为类型 T 的对象

1.T 可以是预定义类型,也可以是用户定义类型

2.函数没有参数,没有返回类型,但必须有一条 return 语句,返回 T 类型的对象
3.该函数只能为成员函数,不能为友元

class  X
{  ……
   public :
        operator  int ( ) ;
   ……
} ;
void  f ( X  a )
{ int  i = int ( a ) ;
   i = ( int ) a ;        //调用: (转换的目标类型)对象名
   i = a ;
}

小结

当一元运算符的操作数,或者二元运算符的左操作数是类的一个对象时,以成员函数重载

当一个运算符的操作需要修改类对象状态时,应该以成员函数重载;如果以友元函数重载,则使用引用参数修改对象。 例如:自增/减

运算符的操作数(尤其是第一个操作数)希望有隐式转换,则重载算符时必须用友元函数

构造函数和类型转换函数可以实现类型转换(基本类型与类类型,以及类类型之间)。

//成员函数重载
返回类型 operator op(运算符)(参数表)
{
//相对于该类定义的操作;
}
成员函数重载默认运算符左数据为类数据成员

//友元函数重载
friend  返回类型 opeartor op(运算符)(参数表)
{
//相对于该类定义的操作
}
//重载有赋值含义的运算符时有在opeartor 前面加& (引用). 比如 []

对于赋值运算符和地址运算符系统提供默认默认重载版本
赋值运算符 = ,系统默认重载为对象数据成员的赋值
地址运算符 & ,系统默认重载为返回任何类对象的地址

一元运算符只对一个类对象进行操作,不论前置或者后置,都要求有且仅有一个操作数。对于成员函数数,操作对象有this指针隐含传递;对于友元函数们需要用形参表示

二元运算符都需要左,右两个操作数。成员函数左操作数由this指针隐含提供,右指针由参数表提供。友元函数左右操作数皆由参数表提供

赋值运算=,下标运算符 [],(),->,必须为成员函数
输入输出 << ,>>, 必须重载为友元函数
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值