運(yùn)算符重載

一、運(yùn)算符重載的概念

重載運(yùn)算符的概念

C++中的表達(dá)式由運(yùn)算符和操作數(shù)按照規(guī)則構(gòu)成。

運(yùn)算符重載就是給已有的運(yùn)算符賦予多重含義,使同一個(gè)運(yùn)算符作用于不同類型的數(shù)據(jù)時(shí)產(chǎn)生不同的行為。

運(yùn)算符重載的目的時(shí)使得C++中的運(yùn)算符也能夠用來操作對(duì)象。

表4-1 可重載的運(yùn)算符

可重載的運(yùn)算符 說明
雙目算數(shù)運(yùn)算符 +(加),-(減),*(乘),/(除).%(取模)
關(guān)系運(yùn)算符 ==(等于),!=(不等于),<(小于),>(大于),<=(小于等于),>=(大于等于)
邏輯運(yùn)算符 ||(邏輯或),&&(邏輯與),!(邏輯非)
單目運(yùn)算符 +(正),-(負(fù)),*(指針),&(取地址)
自增自減運(yùn)算符 ++(自增),--(自減)
位運(yùn)算符 |(按位或),&(按位與),~(按位取反),^(按位異或),<<(左移),>>(右移)
賦值運(yùn)算符 =(賦值),+=(加法賦值),-=(減法賦值),*=(乘法賦值),/=(除法賦值),%=(取模賦值),&=(按位與賦值),|=(按位或賦值),^=(按位異或賦值),<<=(左移賦值),>>=(右移賦值)
空間申請(qǐng)與釋放 new(創(chuàng)建對(duì)象),delete(釋放對(duì)象),new,delete[(釋放數(shù)組)
其他運(yùn)算符 0(函數(shù)調(diào)用),->(成員訪問,,(逗號(hào)),

表4-2 不可重載的運(yùn)算符和符號(hào)

可重載的運(yùn)算符 說明
成員訪問運(yùn)算符 .
成員指針訪問運(yùn)算符 .,->
域運(yùn)算符 ::
長(zhǎng)度運(yùn)算符 sizeof
條件運(yùn)算符 ?:
預(yù)處理符號(hào) #

有兩個(gè)運(yùn)算符,系統(tǒng)提供了默認(rèn)的重載版本。它們是賦值運(yùn)算符=和地址運(yùn)算符&。

對(duì)于=,系統(tǒng)默認(rèn)重載為對(duì)象成員變量的復(fù)制。對(duì)于&,系統(tǒng)默認(rèn)重載為返回任何類對(duì)象的地址。

運(yùn)算符重載的實(shí)質(zhì)是編寫以運(yùn)算符為名稱的函數(shù),使用運(yùn)算符的表達(dá)式就被解釋為對(duì)重載函數(shù)的調(diào)用。

函數(shù)名由關(guān)鍵字operator和其后要重載的運(yùn)算符符號(hào)構(gòu)成。

運(yùn)算符函數(shù)的格式

返回值類型 operator 運(yùn)算符(形參表)
{
  函數(shù)體
}

運(yùn)算符可以被重載為全局函數(shù),也可以被重載為類的成員函數(shù)。

重載運(yùn)算符為類的成員函數(shù)

程序4-1 為類myComplex重載運(yùn)算符“+”和“-”。

#include <iostream>
using namespace std;

class myComplex     //復(fù)數(shù)類 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

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

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex operator+(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom();
    cout<<"operator+";
    c2.outCom();
    cout<<"=";
    res = c1 + c2;
    res.outCom();
    cout<<endl;
    c1.outCom();
    cout<<"operator-";
    c2.outCom();
    cout<<"=";
    res = c1 - c2;
    res.outCom();
    cout<<endl;
    return 0;
}

(1,2)operator+(3,4)=(4,6)
(1,2)operator-(3,4)=(-2,-2)

重載運(yùn)算符為友元函數(shù)

例4-1中定義的operator-(double r)實(shí)現(xiàn)的是復(fù)數(shù)的實(shí)部減去r并返回結(jié)果對(duì)象。

#include <iostream>
using namespace std;

class myComplex     //復(fù)數(shù)類 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        myComplex operator-(double r);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

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

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex myComplex::operator-(double r)
{
    return myComplex(this->real-r,this->imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom();
    cout<<"operator-";
    c2.outCom();
    cout<<"=";
    res = c1 - 2;   //正確
//  res = 2 - c1;   //錯(cuò)誤,不能實(shí)現(xiàn) 
    res.outCom();
    cout<<endl;
    return 0;
}

(1,2)operator-(3,4)=(-1,2)

例4-2 重載為友元函數(shù)

#include <iostream>
using namespace std;

class myComplex     //復(fù)數(shù)類 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);
        friend myComplex operator-(const myComplex &c1,const myComplex &c2);
        friend myComplex operator-(const myComplex &c1,double r);
        friend myComplex operator-(double r,const myComplex &c1);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

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

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex operator+(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);
}

myComplex operator-(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real - c2.real,c1.imag - c2.imag);
}

myComplex operator-(const myComplex &c1,double r)
{
    return myComplex(c1.real - r,c1.imag);
}

myComplex operator-(double r,const myComplex &c1)
{
    return myComplex(r - c1.real,-c1.imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    res = c1 + c2;
    res.outCom();
    res = c1 - 5;
    res.outCom();
    res = 5 - c1;
    res.outCom();
    
    
    return 0;
}

(4,6)(-4,2)(4,-2)

重載運(yùn)算符的規(guī)則

在C++中進(jìn)行運(yùn)算符重載時(shí),有以下規(guī)則:

  • 重載后運(yùn)算符的含義應(yīng)該符合原有的用法習(xí)慣。
  • 運(yùn)算符重載不能改變運(yùn)算符原有的語義,包括運(yùn)算符的優(yōu)先級(jí)和結(jié)合性。
  • 運(yùn)算符重載不能改變運(yùn)算符操作數(shù)的個(gè)數(shù)及語法結(jié)構(gòu)。
  • 不能創(chuàng)建新的運(yùn)算符,即重載運(yùn)算符不能超出C++語言允許重載的運(yùn)算符范圍。
  • 重載運(yùn)算符() [] ->或者賦值運(yùn)算符=時(shí),只能將它們重載為成員函數(shù),不能重載為全局函數(shù)。
  • 運(yùn)算符重載不能改變?cè)撨\(yùn)算符用于基本數(shù)據(jù)類型對(duì)象的含義。

二、重載賦值運(yùn)算符

重載賦值運(yùn)算符

C++中的賦值運(yùn)算符“=”要求左右兩個(gè)操作數(shù)的類型時(shí)匹配的,或至少是賦值兼容的。

C++規(guī)定,“=”只能重載為成員函數(shù)。

程序4-2 為類myComplex重載賦值運(yùn)算符

#include <iostream>
using namespace std;

class myComplex     //復(fù)數(shù)類 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        ~myComplex(){}
        myComplex addCom(myComplex c1); //成員函數(shù),調(diào)用對(duì)象與參數(shù)對(duì)象c1相加 
        void outCom();
        void outCom(string s);
        void changeReal(double r);  //成員函數(shù)
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);    //c1+c2
        friend myComplex operator+(const myComplex &c1,double r);       //c1+r
        friend myComplex operator+(double r,const myComplex &c1);       //r+c1
        friend myComplex operator-(const myComplex &c1,const myComplex &c2);    //c1-c2
        friend myComplex operator-(const myComplex &c1,double r);       //c1-r
        friend myComplex operator-(double r,const myComplex &c1);       //r-c1
        myComplex &operator=(const myComplex &c);       //成員函數(shù) 
        myComplex &operator=(double);       //成員函數(shù) 
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

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

myComplex myComplex::addCom(myComplex c1)
{
    return myComplex(this->real + c1.real,this->imag + c1.imag);
 } 

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

void myComplex::outCom(string s)
{
    cout<<s<<"=("<<real<<","<<imag<<")"<<endl;
}

void myComplex::changeReal(double r)
{
    this->real=r;
}

myComplex operator+(const myComplex &c1,const myComplex &c2)  //c1+c2
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);  //返回一個(gè)臨時(shí)對(duì)象 
}

myComplex operator+(const myComplex &c1,double r)   //c1+r
{
    return myComplex(c1.real + r,c1.imag);
}


myComplex operator+(double r,const myComplex &c1)       //r+c1
{
    return myComplex(r+c1.real,c1.imag);
}

myComplex operator-(const myComplex &c1,const myComplex &c2)    //c1-c2
{
    return myComplex(c1.real - c2.real,c1.imag - c2.imag);
}

myComplex operator-(const myComplex &c1,double r)   //c1-r
{
    return myComplex(c1.real- r,c1.imag);
}


myComplex operator-(double r,const myComplex &c1)       //r-c1
{
    return myComplex(r-c1.real,-c1.imag);
}

myComplex &myComplex::operator=(const myComplex &c1)
{
    this->real = c1.real;
    this->imag = c1.imag;
    return *this;
}

myComplex &myComplex::operator = (double r)
{
    this->real = r;
    this->imag = 0;
    return *this;
}


int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom("\t\tc1");
    c2.outCom("\t\tc2");
    res = c1 + c2;
    res.outCom("執(zhí)行res=c1+c2→\tres");
    res = c1.addCom(c2);
    res.outCom("執(zhí)行res=c1.addCom(c2)→\tres");
    res = c1 + 5;
    res.outCom("執(zhí)行res=c1 + 5→\tres");
    res = 5 + c1;
    res.outCom("執(zhí)行res=5 + c1→\tres");
    
    res = c1;
    c1.outCom("\t\tc1");
    res.outCom("執(zhí)行res=c1→\tres");
    
    c1.changeReal(-3);
    c1.outCom("執(zhí)行c1.changeReal(-3)→\tc1");
    
    res.outCom("\t\tres");
    res = c1;
    res.outCom("執(zhí)行res=c1→\tres");
    
    res = 7;
    res.outCom("執(zhí)行res=7→\tres");
    
    res = 7+8;
    res.outCom("執(zhí)行res=(7+8)→\tres");
    
    res= c1 = c2;
    c1.outCom("\t\tc1");
    c2.outCom("\t\tc2");
    res.outCom("執(zhí)行res=c1=c2→\tres");
    return 0;
}

                c1=(1,2)
                c2=(3,4)
執(zhí)行res=c1+c2→ res=(4,6)
執(zhí)行res=c1.addCom(c2)→ res=(4,6)
執(zhí)行res=c1 + 5→        res=(6,2)
執(zhí)行res=5 + c1→        res=(6,2)
                c1=(1,2)
執(zhí)行res=c1→    res=(1,2)
執(zhí)行c1.changeReal(-3)→ c1=(-3,2)
                res=(1,2)
執(zhí)行res=c1→    res=(-3,2)
執(zhí)行res=7→     res=(7,0)
執(zhí)行res=(7+8)→ res=(15,0)
                c1=(3,4)
                c2=(3,4)
執(zhí)行res=c1=c2→ res=(3,4)

關(guān)于重載賦值運(yùn)算符應(yīng)注意

  • 賦值運(yùn)算符必須重載為成員函數(shù)
  • 為了保持與通常意義下的賦值運(yùn)算符的功能相一致,應(yīng)該讓重載的賦值運(yùn)算符能連續(xù)使用。

淺拷貝和深拷貝

同類對(duì)象之間可以通過賦值運(yùn)算符“=”互相賦值。如果沒有經(jīng)過重載,“=”的作用就是將賦值號(hào)右側(cè)對(duì)象的值一一賦值給左側(cè)的對(duì)象。這相當(dāng)于值的拷貝,稱為“淺拷貝”。

程序4-3 淺拷貝的含義

#include <iostream>
using namespace std;

class pointer
{
    public:
        int a;
        int *p;
        pointer()
        {
            a = 100;
            p = new int(10);
        }
        pointer(const pointer &tempp)
        {
            if(this != &tempp)
            {
                a = tempp.a;
                p = tempp.p;
            }
        }
};

int main()
{
    pointer p1;
    pointer p2(p1); //使用復(fù)制構(gòu)造函數(shù) 
    pointer p3 = p1;    //使用復(fù)制構(gòu)造函數(shù) 
    cout<<"\n初始化后,各對(duì)象的值及內(nèi)存地址:"<<endl;
    cout<<"對(duì)象名\t對(duì)象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    
    *p1.p = 20;
    p2.a = 300;
    cout<<"\n修改后,各對(duì)象的值及內(nèi)存地址:"<<endl;
    cout<<"對(duì)象名\t對(duì)象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    return 0; 
}

初始化后,各對(duì)象的值及內(nèi)存地址:
對(duì)象名  對(duì)象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x891500,               10,             0x6ffdf8
p2:     0x6ffde0,               100,            0x891500,               10,             0x6ffde8
p3:     0x6ffdd0,               100,            0x891500,               10,             0x6ffdd8

修改后,各對(duì)象的值及內(nèi)存地址:
對(duì)象名  對(duì)象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x891500,               20,             0x6ffdf8
p2:     0x6ffde0,               300,            0x891500,               20,             0x6ffde8
p3:     0x6ffdd0,               100,            0x891500,               20,             0x6ffdd8

重載賦值運(yùn)算符后,賦值語句的功能是將一個(gè)對(duì)象中指針成員變量指向的內(nèi)容復(fù)制到另一個(gè)對(duì)象中指針成員變量指向的地方,這樣的拷貝叫“深拷貝”。
程序4-4 深拷貝的實(shí)現(xiàn)

#include <iostream>
using namespace std;
class pointer
{
    public:
        int a;
        int *p;
        pointer()
        {
            a = 100;
            p = new int(10);
        }
        pointer(const pointer &tempp)
        {
            if(this != &tempp)
            {
                a = tempp.a;
                p = tempp.p;
                *p = *tempp.p;
            }
        }
        ~pointer()
        {
            if(p != NULL)delete p;
        }
        pointer &operator=(const pointer &c)
        {
            if(this == &c)return *this;
            delete this->p;
            this->p = new int(*c.p);
            return *this;
        }
};

int main()
{
    pointer p1;
    pointer p2(p1); //使用復(fù)制構(gòu)造函數(shù) 
    pointer p3;
    p1 = p1;
    p3 = p1;
    cout<<"\n初始化后,各對(duì)象的值及內(nèi)存地址:"<<endl;
    cout<<"對(duì)象名\t對(duì)象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    
    *p1.p = 20;
    p2.a = 300;
    cout<<"\n修改后,各對(duì)象的值及內(nèi)存地址:"<<endl;
    cout<<"對(duì)象名\t對(duì)象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    return 0; 
}

初始化后,各對(duì)象的值及內(nèi)存地址:
對(duì)象名  對(duì)象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x171500,               10,             0x6ffdf8
p2:     0x6ffde0,               100,            0x171500,               10,             0x6ffde8
p3:     0x6ffdd0,               100,            0x171520,               10,             0x6ffdd8

修改后,各對(duì)象的值及內(nèi)存地址:
對(duì)象名  對(duì)象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x171500,               20,             0x6ffdf8
p2:     0x6ffde0,               300,            0x171500,               20,             0x6ffde8
p3:     0x6ffdd0,               100,            0x171520,               10,             0x6ffdd8

三、重載流插入運(yùn)算符和流提取運(yùn)算符

在C++中,左移運(yùn)算符“<<”可以和cout一起用于輸出,故常被稱為“流插入運(yùn)算符”。

右移運(yùn)算符“>>”和cin一起用于輸入,稱為“流提取運(yùn)算符”。

流是標(biāo)準(zhǔn)庫,用戶程序中只能繼承不能修改,所以重載函數(shù)不能是流類庫中的成員,而必須重載為類的友元。
重載流插入運(yùn)算符的一般格式

ostream &operator<<(ostream & output,類名&對(duì)象名)
{
  ...
  return output;
}

重載流提取運(yùn)算符的一般格式

istream &operator>>(istream & input,類名&對(duì)象名)
{
  ...
  return input;
}

程序4-5 流插入運(yùn)算符和流提取運(yùn)算符重載為友元

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

class myComplex
{
    private:
        double real,imag;
    public:
        myComplex():real(0),imag(0){}
        myComplex(double r,double i):real(r),imag(i){}
        friend ostream &operator<<(ostream &os,const myComplex & c);
        friend istream &operator>>(istream &is,myComplex &c);
};

ostream & operator<<(ostream &os,const myComplex &c)
{
    if(c.imag >=0)
    {
        os<<c.real<<"+"<<c.imag<<"i";
    }else
    {
        os<<c.real<<"-"<<(-c.imag)<<"i";
    }
    return os;
}

istream & operator >>(istream &is,myComplex &c)
{
    string s;
    is>>s;      //將a+bi作為字符串讀入,a+bi中間不能有空格
    int pos = s.find("+",0);    //查找虛部
    if(pos == -1)pos = s.find("-",1);       //虛部為復(fù)數(shù)時(shí)
    string sReal = s.substr(0,pos); //分離出代表實(shí)部的字符串
    c.real = atof(sReal.c_str());   //atof()能將參數(shù)內(nèi)容轉(zhuǎn)換成浮點(diǎn)數(shù)
    sReal = s.substr(pos,s.length()-pos-1); //分離出代表虛部的字符串
    c.imag = atof(sReal.c_str());
    return is; 
}

int main()
{
    myComplex c,c1;
    int n;
    cout<<"請(qǐng)輸入兩個(gè)復(fù)數(shù)([-]a±bi)和一個(gè)整數(shù),以空格分隔"<<endl;
    cin>>c>>c1>>n;
    cout<<c<<","<<n<<","<<c1;
    return 0; 
}

請(qǐng)輸入兩個(gè)復(fù)數(shù)([-]a±bi)和一個(gè)整數(shù),以空格分隔
3.4-3i -5+6i 36
3.4-3i,36,-5+6i

程序4-6 流插入運(yùn)算符重載為成員函數(shù)

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

class myComplex
{
    private:
        double real,imag;
    public:
        myComplex():real(0),imag(0){}
        myComplex(double r,double i):real(r),imag(i){}
        ostream &operator<<(ostream &os);
        friend istream &operator>>(istream &is,myComplex &c);
};

ostream & myComplex::operator<<(ostream &os)
{
    if(this->imag >=0)
    {
        os<<this->real<<"+"<<this->imag<<"i";
    }else
    {
        os<<this->real<<"-"<<(-this->imag)<<"i";
    }
    return os;
}

istream & operator >>(istream &is,myComplex &c)
{
    string s;
    is>>s;      //將a+bi作為字符串讀入,a+bi中間不能有空格
    int pos = s.find("+",0);    //查找虛部
    if(pos == -1)pos = s.find("-",1);       //虛部為復(fù)數(shù)時(shí)
    string sReal = s.substr(0,pos); //分離出代表實(shí)部的字符串
    c.real = atof(sReal.c_str());   //atof()能將參數(shù)內(nèi)容轉(zhuǎn)換成浮點(diǎn)數(shù)
    sReal = s.substr(pos,s.length()-pos-1); //分離出代表虛部的字符串
    c.imag = atof(sReal.c_str());
    return is; 
}

int main()
{
    myComplex c,c1;
    int n;
    cout<<"請(qǐng)輸入兩個(gè)復(fù)數(shù)([-]a±bi)和一個(gè)整數(shù),以空格分隔"<<endl;
    cin>>c>>c1>>n;
    c1<<(c<<cout<<",")<<","<<n;
    return 0; 
}

請(qǐng)輸入兩個(gè)復(fù)數(shù)([-]a±bi)和一個(gè)整數(shù),以空格分隔
3.4-3i -5+6i 36
3.4-3i,-5+6i,36

*四、重載強(qiáng)制類型轉(zhuǎn)換運(yùn)算符

在C++中,類型的名字(包括類的名字)本身意識(shí)一種運(yùn)算符,即強(qiáng)制類型轉(zhuǎn)換運(yùn)算符。

強(qiáng)制類型轉(zhuǎn)換運(yùn)算符是單目運(yùn)算符,也可以被重載,但只能重載為成員函數(shù),不能重載為全局函數(shù)。

程序4-7 重載強(qiáng)制類型轉(zhuǎn)換運(yùn)算符double

#include <iostream>
using namespace std;

class myComplex
{
    double real,imag;
    public:
        myComplex(double r=0,double i=0):real(r),imag(i){}
        operator double()
        {
            return real;
        }
};

int main()
{
    myComplex c(1.2,-3.4);
    cout<<(double)c<<endl;
    double n = 12+c;
    cout<<n;
    return 0;
}

1.2
13.2

五、重載自增、自減運(yùn)算符

自增運(yùn)算符“++”和自減運(yùn)算符“--”都可以被重載,但是它們有前置和后置之分。

運(yùn)算符重載相當(dāng)于定義了一個(gè)以運(yùn)算符為名字的函數(shù)。以自增運(yùn)算符為例,可以表示為:

CDemo & CDemo::operator++()
{
  ...
  return *this;
}

這樣的函數(shù)不能區(qū)分前置及后置情況。

C++規(guī)定,在重載“++”或“--”時(shí),允許寫一個(gè)增加了無用int類型形參的版本,編譯器處理“++”或“--”前置的表達(dá)式時(shí),調(diào)用參數(shù)個(gè)數(shù)正常的重載函數(shù);處理后置的表達(dá)式時(shí),調(diào)用多出一個(gè)參數(shù)的重載函數(shù)。

程序4-8 自增運(yùn)算符重載為成員函數(shù),自減運(yùn)算符重載為友元。

#include <iostream>
using namespace std;

class CDemo
{
    private:
        int n;
    public:
        CDemo(int i = 0):n(i){}
        CDemo & operator++();       //用于前置形式
        CDemo & operator++(int);    //用于后置形式
        operator int() {return n;}
        friend CDemo & operator--(CDemo &);
        friend CDemo operator--(CDemo &,int);
};

CDemo & CDemo::operator++()     //前置++ 
{
    n++;
    return *this;
}

CDemo & CDemo::operator++(int k)    //后置++,多一個(gè)參數(shù) 
{
    CDemo tmp(*this);       //記錄修改前的對(duì)象 
    n++;
    return tmp;         //返回修改前的對(duì)象 
}

CDemo & operator--(CDemo & d)   //前置-- 
{
    d.n--;
    return d;
}

CDemo operator--(CDemo & d,int)     //后置-- 
{
    CDemo tmp(d);
    d.n--;
    return tmp; 
 } 
 
int main()
{
    CDemo d(10);
    cout<<"(d++)="<<(d++)<<",";     //等價(jià)于“d.operator++(0);”輸出10
    cout<<"\nd="<<d<<",";           //輸出11 
    cout<<"\n(++d)="<<(++d)<<",";       //等價(jià)于“d.operator++();”輸出12
    cout<<"\nd="<<d<<",";               //輸出12
    cout<<"\n(d--)="<<(d--)<<",";       //等價(jià)于“d.operator--(0);”輸出12
    cout<<"\nd="<<d<<",";               //輸出11
    cout<<"\n(--d)="<<(--d)<<",";       //等價(jià)于“d.operator--();”輸出10
    cout<<"\nd="<<d<<endl;              //輸出10
    return 0;
}


(d++)=10,
d=11,
(++d)=12,
d=12,
(d--)=12,
d=11,
(--d)=10,
d=10

程序4-9 自增、自減運(yùn)算符重載為成員函數(shù)

#include <iostream>
using namespace std;

class CDemo
{
    private:
        int n;
    public:
        CDemo(int i = 0):n(i){}
        CDemo & operator++();       //用于前置形式
        CDemo & operator++(int);    //用于后置形式
        operator int()
        {
            return n;
        }
        CDemo & operator--();
        CDemo operator--(int);
};

CDemo & CDemo::operator++()     //前置++ 
{
    n++;
    return *this;
}

CDemo & CDemo::operator++(int k)    //后置++,多一個(gè)參數(shù) 
{
    CDemo tmp(*this);       //記錄修改前的對(duì)象 
    n++;
    return tmp;         //返回修改前的對(duì)象 
}

CDemo & CDemo::operator--() //前置-- 
{
    n--;
    return *this;
}

CDemo CDemo::operator--(int k)      //后置-- 
{
    CDemo tmp(*this);
    n--;
    return tmp; 
 } 
 
int main()
{
    CDemo d(10);
    cout<<"(d++)="<<(d++)<<",";     //等價(jià)于“d.operator++(0);”輸出10
    cout<<"\nd="<<d<<",";           //輸出11 
    cout<<"\n(++d)="<<(++d)<<",";       //等價(jià)于“d.operator++();”輸出12
    cout<<"\nd="<<d<<",";               //輸出12
    cout<<"\n(d--)="<<(d--)<<",";       //等價(jià)于“d.operator--(0);”輸出12
    cout<<"\nd="<<d<<",";               //輸出11
    cout<<"\n(--d)="<<(--d)<<",";       //等價(jià)于“d.operator--();”輸出10
    cout<<"\nd="<<d<<endl;              //輸出10
    return 0;
}

(d++)=10,
d=11,
(++d)=12,
d=12,
(d--)=12,
d=11,
(--d)=10,
d=10
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 運(yùn)算符重載的概念 C++中的表達(dá)式由運(yùn)算符和操作數(shù)按照規(guī)則構(gòu)成。例如,算術(shù)運(yùn)算符包括加+、減-、乘*、除/和取模%...
    silasjs閱讀 788評(píng)論 0 1
  • 運(yùn)算符重載 運(yùn)算符重載的概念 在C++中,基本的算數(shù)運(yùn)算符,如果不做特殊處理,則 不能用于對(duì)象之間的運(yùn)算 。 運(yùn)算...
    陳_MY閱讀 554評(píng)論 0 0
  • 基本概念 重載的運(yùn)算符本質(zhì)上是具有特殊名字的函數(shù),名字由關(guān)鍵字operator和后面要定義的運(yùn)算符號(hào)共同組成。該函...
    Kreat閱讀 659評(píng)論 0 0
  • 01 運(yùn)算符重載的需求 C++ 預(yù)定義的運(yùn)算符,只能用于基本數(shù)據(jù)類型的運(yùn)算:整型、實(shí)型、字符型、邏輯型等等,且不能...
    小林coding閱讀 305評(píng)論 0 0
  • 技術(shù)交流QQ群:1027579432,歡迎你的加入! 1.Cpp中的重載運(yùn)算符和重載函數(shù) C++允許在同一作用域中...
    CurryCoder閱讀 573評(píng)論 0 1

友情鏈接更多精彩內(nèi)容