0
点赞
收藏
分享

微信扫一扫

面试笔记——Redis(使用场景、面临问题、缓存穿透)

醉东枫 03-19 07:30 阅读 3

文章目录

一、运算符重载规则

1. 重载运算符的限制

可以重载的运算符

+	-	*	/	%	^	&	|	~
!	=	<	>	+=	-=	*=	/=	%
^=	&=	|=	<<	>>	>>=	<<=	==	!=
<=	>=	&&	||	++	--	->*	‘	->
[]	()	new	delete	new[]	delete[] 

不能重载的算符

.	::	.*	?:	sizeof

重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:

1.不改变运算符的优先级
2.不改变运算符的结合性
3.不改变运算符所需要的操作数 
4.不能创建新的运算符

2.运算符重载的语法形式

运算符函数是一种特殊的成员函数或友元函数
成员函数的语法形式为:

类型(返回类型)   类名(重载该运算的类)  ::  operator  op(被重载的运算符) ( 参数表 )
{
      // 相对于该类定义的操作
}

一个运算符被重载后,原有意义没有失去,只是定义了相对一特定类的一个新运算符

#include<iostream>
#include<cstdlib>
using namespace std;
class Calculator
{ public:
    Calculator() { value = 0 ; } ;
    void operator ++ () ;
    void operator -- () ; 
    unsigned int operator() () ;
  private:
    unsigned int value;
}; 
int main()
{ Calculator Counter ;
   int i ;
   for( i = 0 ; i < 5 ; i ++ )
      { ++ Counter;
         cout << "\n Counter = " << Counter() ;
      }
   for( i = 0 ; i <= 5 ; i ++ )
      { -- Counter;
         cout << "\n Counter = " << Counter() ;
      }
} 
void Calculator::operator ++ ()
{ if ( value < 65535 ) value ++ ;
  else
    { cout << "\nData overflow !" << endl ;
      exit( 0 ) ;
    }
} 
void Calculator::operator --()
{ if ( value > 0 ) value -- ;
  else
    { cout << "\n Data overflow !" << endl ;
      exit( 0 ) ;
    }
}
unsigned int Calculator::operator() ()
{ return value ; }
 

二、用成员或友元函数重载运算符

1.一元运算符

Object op 或 op Object

①重载为成员函数,解释为:

Object . operator op ()

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

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

②重载为友元函数,解释为:

operator op (Object)

​ 操作数由参数表的参数Object提供

​ 操作数由参数表的参数Object提供

2.二元运算符

ObjectL op ObjectR

①重载为成员函数,解释为:

ObjectL . operator op ( ObjectR )

​ 左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递

②重载为友元函数,解释为:

operator op ( ObjectL, ObjectR )

左右操作数都由参数传递

3.用成员函数重载运算符

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

成员函数不能适用于左操作数不是本身的运算符重载

举例:建立一个描述3维坐标的类 Tri_Coor,重载运算符 “+”、“++”、和 “=” ,实现简单的算术运算

#include<iostream>
using namespace std;
class TriCoor
{ public:
       TriCoor( int mx = 0, int my = 0, int mz = 0 ) { x = mx ; y = my ; z = mz ; }
       TriCoor operator + ( TriCoor t ) 
          { TriCoor temp ;
             temp.x = x+t.x ;  temp.y = y+t.y ;  temp.z = z+t.z ;
             return temp ;
          }
       TriCoor operator = ( TriCoor t ) { x = t.x ;  y = t.y ;  z = t.z ;  return  &this ; }
 //可以将TriCoor t 转换为const TriCoor& t 来避免拷贝构造带来的浪费
       TriCoor operator ++ () { x ++ ;  y ++ ;  z ++ ;  return &this ; }
       void show() { cout << x << " , " << y << " , " << z << "\n"; }
       void assign( int mx, int my, int mz ) { x = mx;  y = my;  z = mz; }
  private:       int x, y, z ;	// 3_d coordinates
} ;
 
int main()
{ TriCoor a( 1, 2, 3 ), b, c ;
  a.show();  b.show();  c.show();
  for( int i = 0;  i < 5;  i ++ ) ++ b;      b.show() ;
  c.assign( 3, 3, 3 ) ;    c = a + b + c ;    c.show() ;
  c = b = a ;    c.show() ;
} 

4.用友元函数重载

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

例如:

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 ;	//左操作数为27不能使用成员函数	
      …...
}
①条件
②例子
#include<iostream>
using namespace std;
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 ; }
int main()
{ Complex  c1( 2.5,3.7 ), c2( 4.2, 6.5 ) ;
   Complex c ;
   c = c1 - c2 ;	// operator-(c1,c2)
   c.print() ;
   c = 25 + c2 ;	// operator+(25,c2)
   c.print() ;
   c = c2 + 25 ;	// operator+(c2,52)
   c.print() ;
   c = - c1 ;	// operator-(c1)
   c.print() ;
}


③注意
  1. friend的作用:

    举例:

    Complex operator - ( const Complex & c1, const Complex & c2 )
      { double r = c1.Real - c2.Real ;  double i = c1.Image - c2.Image ;
         return Complex ( r,  i ) ;
      }
    

    虽然在这个函数中,这个类的实例可以调用本身的私有数显

    但是对于传入的参数const Complex & c1, const Complex & c2的私有属性,这个函数如果不是友元函数那么就不难调用c1.Real等

5.讨论

用友元函数重载像“++”这样的运算符时,有时会碰到问题。

例如,

①类 TriCoor 用成员函数重载“++”的版本是:

TriCoor TriCoor :: operator ++ () 
	 { x ++ ;  y ++ ;  z ++ ;  return *this ; }   // ok , 修改了this 指针所指对象

用成员函数重载一元运算符时,所需要的唯一变元通过 this 指针传递,
对 this 所指对象数据的任何改变都会影响到激活运算符函数的对象。

②若定义友元函数 friend operator ++( ) 版本:

 TriCoor operator ++ (TriCoor opl )	
	{ opl . x ++ ;   opl . y ++ ;    opl . z ++ ;    return   opl ; }
//函数使用传值参数,对 opl 的所有修改都无法传到函数体外,不会影响被调用的对象

③用指向激活对象的指针定义友元函数:

	 TriCoor operator ++ ( TriCoor * opl )	
	{ opl -> x ++ ;   opl -> y ++ ;    opl -> z ++ ;    return   *opl ; 
	
	 TriCoor  ob ( 1 , 2 , 3 ) ;
	&ob ++ ;	// error

二义性:对 ob 的地址进行递加?还是将对象 ob 递加?

④使用引用参数:

	 TriCoor operator ++ ( TriCoor & opl )	
	    { opl . x ++;   opl . y ++;    opl . z ++;    return   opl ; }
	    
	     TriCoor ob ( 1 , 2 , 3 ) ;··
	 ob ++;		// ok,传名

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

6.总结

①若一运算符的操作需要修改类对象状态时,应该用成员函数重载;
需要左值操作数的运算符(如 ++,–),若重载为友元函数时要用引用参数

②C++不能用友元重载的运算符: = () [] ->

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

举报

相关推荐

0 条评论