重载运算符总结

重载运算符

1.不能重载的5个运算符

.   .*   ::   ?:  sizeof

2重载运算符的限制

①不改变运算符的优先级

②不改变运算符的结合性

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

3.运算符重载是一种特殊的成员函数或友元函数

   成员函数语句格式

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

   类型指函数的返回类型 类名是要重载该运算符的类 op是要重载的运算符 函数名是operator op 参数表列出该运算符所需要的    操作数

4.一元运算符(一个操作数)

Objectop或op Object

(1)当重载为成员函数时,编译器解释为Object operator op()

函数operator op所需的操作数由对象Object通过this指针隐含传递,所以参数表为空

(2)重载为友元函数,解释为operator op (Object)

函数operator op所需的操作数由参数表的参数Object提供

5.二元运算符(两个操作数)

二元运算符要求有左右两个操作数ObjectL  op ObjectR

(1)重载为成员函数,解释为ObjectL . operator op (ObjectR )

    左操作数由对象ObjectL通过this指针传递,右操作数由参数ObjectR传递(一般用传引用&)

(2)重载为友元函数,解释为operator op ( ObjectL,ObjectR )

      左右操作数都由参数传递

 注:用成员函数或友元函数重载关键区别 成员函数有this指针 友元函数没有this指针

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

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

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

class X {
    //…
返回类型 operator运算符(形参表);
  //…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
     函数体
}
注:对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过 this指针 隐含地传递给函数的。
对单目运算符而言,成员运算符函数的参数表中 没有参数, 此时当前对象作为运算符的一个操作数。

例:
有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。
class Time
{
public:
		Time( ){minute=0;sec=0;}
		Time(int m,int s):minute(m),sec(s){ }
		Time operator++( );     //声明前置自增运算符“++”重载函数
		Time operator++(int);   //声明后置自增运算符“++”重载函数
private:
		int minute;
		int sec;
};
Time Time∷operator++( )    //定义前置自增运算符“++”重载函数
{
	if(++sec>=60)	{	
		sec-=60;         //满60秒进1分钟
		++minute;
	}
	return *this;          //返回当前对象值
}
Time Time∷operator++(int)  //定义后置自增运算符“++”重载函数
{
	Time temp(*this);
	sec++;
	if(sec>=60)	{
		sec-=60;
		++minute;
	}
	return temp;         //返回的是自加前的对象
}
7.友元重载
友元函数重载运算符常用于运算符的左右操作数类型不同的情况
(1) 在第一个参数需要隐式转换的情形下,使用友元函数重载 运算符是正确的选择
(2) 友元函数没有 this 指针,所需操作数都必须在参数表显式 声明,很容易实现类型的隐式转换
(3) C++ 不能 用友元函数重载的运算符有
             =    ()    []    ->
例:复数运算
#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 ; }

注: 成员运算符函数与友元运算符函数的比较
  (1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
  (2)  双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
 

8.典型运算符重载


(1)++与--

  • 前置方式: ++Aobject --Aobject

  成员函数重载 A :: A operator++ () ;
解释为: Aobject . operator ++( ) ;
    友元函数重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;
  • 后置方式: Aobject++ Aobject --
  成员函数重载 A :: A  operator++ (int) ;
解释为: Aobject . operator ++( 0 ) ; 前+参数表为空 后+operator++(int))
    友元函数重载: 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'; } ;
     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( ) ;
 }

友元重载++

#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( ) ;
 }

(2)重载赋值运算符=

赋值运算符重载用于对象数据的复制
 operator= 必须重载为 成员函数
重载函数原型为:
类名  &  类名  :: operator= ( 类名 ) ;

(3)重载运算符[]和()

运算符 [] 和 () 是二元运算符
[] 和 () 只能用成员函数 重载,不能用友元函数重载
  • []运算符用于访问数据对象的元素
重载格式 类型  类 :: operator[]  ( 类型 ) ;
例如,类X有重载函数:int & X::operator[](int);     求第几个数

其中,x是X类的对象,则调用函数的表达式:x[k]      被解释为:x.operator[](K)

  • ()运算符用于函数调用
    重载格式 类型  类 :: operator()  ( 参数表  ) ;
    设 x 是类 X 的一个对象,则表达式
    x ( arg1, arg2, … )
    可被解释为
    x . operator () (arg1, arg2, … )

(4)重载<<和>>(只能重载为友元函数)


运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
  • 重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)
       定义输出运算符 << 重载函数的一般格式如下 :
    ostream& operator<<(ostream& out,class_name& obj)
    {
          out<<obj.item1;
          out<<obj.item2;
          .. .
          out<<obj.itemn;
          return out;
    }//全输出

  • 重载输入运算符“>>” (只能被重载成友元函数)
          定义输入运算符函数 >> 重载函数的一般格式如下 :
    istream& operator>>(istream& in,class_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 << " 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 ;
}

9.心得体会

    使用重载运算符后,程序更加直观简洁,能够自己定义需要的操作类型,但是在写ATM程序中想要尝试使用重载运算符,不知道如何下手,不知道应该改哪些部分,对着课本现有的程序改了一小部分,但是有的地方没有调通,对于重载运算符的使用规则和用法还是有很多疑问。主要存在的问题有使用成员函数和友元函数的用法区别,应该注意哪些情况使用友元 哪些使用成员函数,语法规则如何。在判断时间时用重载运算符<简化代码,更加直观,一个数据对象整体输入整体输出 用<< 全输入,用>>全输出。在调好一个程序后,可以尝试着使用重载运算符简化程序,使程序功能更加清晰明了,多加练习,逐渐熟悉重载的使用语法形式,尤其是重载<和<<与>>,当然前提是要掌握成员函数与友元函数的使用语法规则。现在还没有体会到重载运算符的突出之处,尝试在程序中使用一些重载,慢慢领悟它的独到之处。

 


<think>好的,我现在需要帮助用户了解在ACM编程竞赛中运算符重载的实现与用法。首先,我需要整理用户提供的引用内容,看看有哪些相关的信息可以参考。 用户提到的引用1和2都提到了复数类的运算符重载,特别是重载+、*和<<运算符。引用2还提到了两种重载方式:类成员函数和全局函数,并且需要友元声明。引用3提到了实验题目,可能涉及具体的实现细节。引用4是关于时间日期类的运算符重载,比如加减运算,这可能与ACM中的实际问题相关。 首先,我应该解释运算符重载的基本概念,说明它在ACM中的作用,比如简化代码,提高可读性。然后,结合用户提供的例子,复数类和时间类,分别展示如何实现常见的运算符重载,比如加减、比较、输入输出等。 接下来,需要区分类成员运算符重载和全局函数重载的不同之处,比如参数数量,是否需要友元等。例如,成员函数的运算符重载,比如operator+,只需要一个参数,因为左操作数是this指针;而全局函数需要两个参数。 然后,在ACM中,常见的应用场景可能包括复数运算、大数运算、矩阵运算、几何计算等,这些都需要重载运算符来简化操作。需要举几个例子,比如矩阵加法或向量的叉乘,用运算符重载如何实现。 另外,注意事项也很重要,比如不能重载运算符(如::、.、.*等),以及运算符的优先级和结合性保持不变。同时,友元函数的使用场景,比如当左操作数不是当前类的对象时,必须使用全局函数重载,比如<<运算符。 最后,总结在ACM中使用运算符重载的好处,比如代码简洁、减少错误,并提醒用户注意合理使用,避免过度复杂化。 现在需要确保回答符合用户的要求,结构清晰,分点说明,并包含相关示例代码,比如复数类的+和<<重载,时间类的加减运算。同时,生成相关问题,帮助用户进一步学习。</think>### ACM竞赛中运算符重载的实现与用法 在ACM编程竞赛中,运算符重载Operator Overloading)是C++中一项重要特性,能够通过自定义类对象的行为,使代码更简洁高效。以下从实现方法和典型应用场景展开说明。 --- #### 一、运算符重载的实现方法 运算符重载分为**类成员函数重载**和**全局函数重载**两种形式,具体选择取决于操作符的语义需求。 1. **类成员函数重载** 运算符作为类的成员函数时,左操作数为当前类的对象(`this`指针),右操作数为参数。 **示例(复数加法)**: ```cpp class Complex { public: Complex(double r = 0, double i = 0) : real(r), imag(i) {} // 成员函数重载 "+" Complex operator+(const Complex& other) { return Complex(real + other.real, imag + other.imag); } private: double real, imag; }; ``` 2. **全局函数重载(需友元声明)** 当左操作数不是当前类对象时(如输入输出流`<<`),需声明为全局函数并配合`friend`关键字。 **示例(复数输出)**: ```cpp class Complex { friend ostream& operator<<(ostream& os, const Complex& c); // 声明友元 }; // 全局重载 "<<" ostream& operator<<(ostream& os, const Complex& c) { os << c.real << "+" << c.imag << "i"; return os; } ``` --- #### 二、ACM中的典型应用场景 1. **复数运算** 直接通过`+`、`*`等运算符实现复数加减乘除,避免手动拆解实虚部。 **乘法重载示例**: ```cpp Complex operator*(const Complex& a, const Complex& b) { return Complex(a.real*b.real - a.imag*b.imag, a.real*b.imag + a.imag*b.real); } ``` 2. **时间/日期计算** 实现时间的加减或比较操作,例如计算时间差[^4]。 **时间加法示例**: ```cpp class Time { public: Time operator+(int seconds) { Time result = *this; result.sec += seconds; // 处理进位逻辑 return result; } }; ``` 3. **几何计算** 向量点乘、叉乘等操作可通过运算符简化: ```cpp Vector3D operator*(const Vector3D& v1, const Vector3D& v2) { return Vector3D(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); // 叉乘 } ``` --- #### 三、注意事项 1. **不可重载运算符** `::`、`.`、`.*`、`sizeof`等运算符不可重载。 2. **保持语义一致性** 例如重载`+`不应修改操作数本身,而是返回新对象。 3. **优先选择成员函数** 对称运算符(如`+`、`==`)可灵活选择,但输入输出流必须全局重载。 --- #### 四、优势总结 - **代码简洁性**:直接通过`a + b`代替`a.add(b)`。 - **可读性提升**:运算符语义直观,如`vector1 * vector2`表示叉乘。 - **减少错误**:封装底层操作,避免重复代码。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值