(GeekBand)C++面向?qū)ο蟾呒壘幊蹋ㄉ希┑谝恢芄P記(2)

第五節(jié) 操作符重載與臨時(shí)對象

今天來分析一下操作符重載。

操作符的重載根據(jù)是否為類成員函數(shù)分為兩種,在分析時(shí)會(huì)涉及到一個(gè)新的知識(shí)點(diǎn):臨時(shí)對象(temp object),語法是typename(),有效域?yàn)橐恍小?/p>

我們來看一下第一種操作符重載,在類中進(jìn)行重載(+=)。

#include<iostream>
using namespace std;

class complex
{
private:
    double re,im;
    friend complex& _doapl(complex*,const complex&);//為重載時(shí)需要調(diào)用的函數(shù)開一個(gè)后門
public:
    complex(double r=0,double i=0):re(r),im(i)//構(gòu)造函數(shù),對re,im進(jìn)行初始化
    {}
    complex& operator +=(const complex&);//重載函數(shù)
    double real() const{return re;}//get re
    double image() const{return im;}//get im
};

inline complex& //申請內(nèi)聯(lián)函數(shù)(與編譯器相關(guān))
complex::operator +=(const complex& r)//傳入右值
{
    return _doapl(this,r);//調(diào)用_doapl(do assignment plus),this指向c2
}

inline complex&//返回*ths的引用
_doapl(complex* ths,const complex& r)//+=新算法(重載實(shí)現(xiàn))
{
    ths->re+=r.re;
    ths->im+=r.im;
    return *ths;  //返回ths指針指向的變量,即c2
}

int main()
{
    complex c1(2,1);
    complex c2(5);
    c2+=c1;
    cout<<"("<<c2.real()<<","<<c2.image()<<")"<<endl;//打印結(jié)果
    return 0;
}


附一張運(yùn)行結(jié)果:

下面來看第二種操作符重載,在類外進(jìn)行重載(+,無this)。

根據(jù)不同類型的加法運(yùn)算多次重載'+'運(yùn)算符。

#include<iostream>
using namespace std;

class complex
{
private:
    double re,im;
public:
    complex(double r=0,double i=0):re(r),im(i)
    {}
    double real() const{return re;}//get re
    double image() const{return im;}//get im
};

inline complex//因?yàn)榉祷嘏R時(shí)object所以用value而不是reference
operator + (const complex& x,const complex& y)
{
    return complex(x.real()+y.real(),x.image()+y.image());
}//對應(yīng)c2=c1+c2

inline complex
operator + (const complex& x,double y)
{
    return complex(x.real()+y,x.image());
}//對應(yīng)c2=c1+5

inline complex
operator + (double x ,const complex& y)
{
    return complex(x+y.real(),y.image());   
}//對應(yīng)c2=7+c1

int main()
{
    complex c1(2,1);
    complex c2(5);
    c2=c1+c2;
    //c2=c1+5;
    //c2=7+c1;
    cout<<"("<<c2.real()<<","<<c2.image()<<")"<<endl;
    return 0;
}


附上一張運(yùn)行結(jié)果:

在眾多操作符中,有一種比較特殊,就是'<<'。在對'<<'操作符進(jìn)行重載時(shí),只能通過

第二種方法,即在全局下重載,下面我們來看一下它的實(shí)現(xiàn)。

#include<iostream>
using namespace std;

class complex
{
private:
    double re,im;
public:
    complex(double r=0,double i=0):re(r),im(i)
    {}
    double real() const{return re;}
    double image() const{return im;}
};

inline ostream&
operator <<(ostream& os,const complex& r)
{
    return os<<'('<<r.real()<<','<<r.image()<<')';
}

int main()
{
    complex c1(2,1);
    cout<<c1<<endl;
    return 0;
}


這里簡單的對操作符'<<'進(jìn)行了重載,使其可是輸入復(fù)數(shù)。那么請思考一下,既然在operator <<(ostream& os,const complex& r)函數(shù)我們已經(jīng)更改了os,為什么還要return呢?

下面我們對代碼稍作更改。

#include<iostream>
using namespace std;

class complex
{
private:
    double re,im;
public:
    complex(double r=0,double i=0):re(r),im(i)
    {}
    double real() const{return re;}
    double image() const{return im;}
};

void operator <<(ostream& os,const complex& r)//將返回類型更改為void
{
    os<<'('<<r.real()<<','<<r.image()<<')';//去掉了return
}

int main()
{
    complex c1(2,1);
    cout<<c1;//輸出c1
    return 0;
}

運(yùn)行結(jié)果:



既然結(jié)果相同,為什么不使用更易理解、使用沒有返回值的方法呢?其實(shí)不然,這種方法有它的弊端,比如我們將主函數(shù)中的cout<<c1換成cout<<c1<<endl,那么在編譯時(shí)就會(huì)報(bào)錯(cuò)。原因是操作符'<<'將左值cout與右值c1傳入重載函數(shù)后會(huì)返回void類型,這時(shí)表達(dá)式變成了void()<<endl,操作符'<<'的左值應(yīng)該是ostream類型而非void類型,所以會(huì)報(bào)錯(cuò)。為了適應(yīng)我們一貫的書寫習(xí)慣,建議使用返回ostream類型的方法。

今天就到這吧,內(nèi)容有點(diǎn)多,還有待消化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容