运算符重载

心得体会:如果不做特殊处理,C++的“+”“-”“*”“/”等等的运算符只能用于最基本的数的运算,而不能用于对象间的运算。如果可以将对象也进行这类操作,程序会更加的简洁,易懂。比如对两个复数对象进行计算。通过运算符的重载,赋予运算符新的功能,就能解决这类对象之间运算的问题。

运算符重载的概念和原理

可以重载的运算符

+   -   *   /   %   ^   &   |   ~

!   =   <   >   +=  -=  *=  /=  %

^=  &=  |=  <<  >>  >>= <<= ==  !=

<=  >=  &&  ||  ++  --  ->* ‘  ->

[]  ()  new delete  new[]   delete[]

不能重载的算符     

.     ::    .*    ?:    sizeof


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

(1)不改变运算符的优先级

(2)不改变运算符的结合性

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

(4)不能创建新的运算符


一元运算符:

Object op 或 op Object

当重载为成员函数时,解释为:Object . operator op ()

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

当重载为友元函数时,解释为:Operator op (Object)

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

二元运算符:

Object op ObjectR

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

ObjectL operator op (ObjectR)

左操作数由ObjectL通过this指针传递,由操作数由函数ObjectR传递

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

operator op (ObjectL , ObjectR)

左右操作数都由参数传递


1. 运算符函数可以重载为成员函数友元函数 

①用成员函数重载运算符:

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

class X {

    //…

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

  //…

}


类外定义成员运算符函数的格式如下:

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

{

     函数体

}

#include <bits/stdc++.h>
using namespace std;
class Complex
{
public:
    double real;
    double imag;
	Complex( ){
	    real=0,imag=0;
	    }
	Complex(double r,double i){
	    real=r;
	    imag=i;
	    }
	 Complex operator + (Complex &c2);
    void display( );
};
    Complex Complex:: 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;
}

②用友元函数重载运算符:

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

①在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择
② 友元函数没有 this指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
③C++中不能用友元函数重载的运算符有 =    ()    []   ->

 #include<bits/stdc++.h>
using namespace std;
class Complex
{
   double  Real,Image ;
   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 ) ;
};
   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()
{
    
}

几个典型运算符重载

1.重载赋值运算符“=”

赋值运算符重载用于对象数据的复制 

operator=必须重载为成员函数

重载函数原型为: 类名   类名   ::operator= ( 类名 ) ; 

赋值运算符“=”要求左右两个操作数的类型是匹配的,或至少是兼容的。有时希望“=”两边的操作数的类型即使不兼容也能够成立,这就需要对“=”进行重载

 #include<bits/stdc++.h>
using namespace std;
class String
{
    char* str;
    public:
    String():str(NULL){}//将stl初始化为NULL仅当执行了operator成员函数后,str才会指向动态分配的存储空间,并且从此后其值不可能再为NULL
    const char* c_str()const{return str;};//函数返回了指向String对象内部动态分配的存储空间的指针,但是不希望外部的到这个指针后修改其指向的字符串的内容,因此将返回类型设为const char*
    String & operator = (const char* s);
    ~String();
};
String&String::operator = (const char* s)
{
    if(str)//在String对象的生存期内,有可能从未执行过operator=成员函数,所以在析构函数中,执行delete【】str之前要先判断str是否为NULL
    delete [] str;
    if(s){
    str=new char[strlen(s)+1];
    strcpy(str,s);
    }
    else
    str=NULL;
    return* this;
}
String::~String()
{
    if(str)//在operator=函数中,要先判断str是否已经指向动态分配的存储空间,如果是,要先释放那片空间,然后重新分配一片空间,再将参数s指向的内容复制过去,这样,对象中存放的字符串就和s指向的字符串一样了
    delete [] str;
}
int main()
{
    String s;
    s="Good Morning,";
    cout<<s.c_str()<<endl;
    s="Mr.Shen";
    cout<<s.c_str()<<endl;
    return 0;
}
//如果没有对=进行重载,s="Good morning,"肯定会因为两边类型不匹配而编译出错


一般地,返回值是被赋值者的引用,即*this原因是

①这样在函数返回时避免一次拷贝,提高了效率。

②更重要的,这样可以实现连续赋值,即类似a=b=c这样。如果不是返回引用而是返回值类型,那么,执行a=b时,调用赋值运算符重载函数,在函数返回时,由于返回的是值类型,所以要对return后边的“东西”进行一次拷贝,得到一个未命名的副,然后将这个副本返回,而这个副本是右值,所以,执行a=b后,得到的是一个右值,再执行=c就会出错。

2.重载自增、自减运算符


成员函数重载++:

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

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

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>  
  
using namespace std;  
  
class Point  
  
{  
  
    int x,y;  
  
public:  
  
    friend istream & operator>>(istream & in, Point &p);  
  
    friend ostream & operator<<(ostream & out,const Point &p);  
  
};  
  
istream & operator>>(istream & in, Point &p)  
  
{  
  
    cout<<"Please input apoint:"<<endl;  
  
    in>>p.x;  
  
    in>>p.y;  
  
    return in;  
  
}  
  
ostream &operator<<(ostream & out,const Point &p)  
  
{  
  
    out<<"("<<p.x<< ","<<p.y <<")"<<endl;  
  
    return out;  
  
}  
  
int main()  
  
{  
  
    Point p;  
  
    cin>>p;  
  
    cout<<p;  
  
    return 0;  
  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值