運(yùn)算符重載(Operator Overloading)

運(yùn)算符重載(Operator Overloading)

操作符重載的要點(diǎn)

  1. 操作符的通用語法
  1. 雙目操作符:<左操作數(shù)><操作符><右操作數(shù)>,簡單表示為,L#R。
  2. 單目操作符:<操作數(shù)><操作符>或<操作符><操作數(shù)>,簡單表示為,O#或#O。
  1. 被重載操作符的操作數(shù)中至少有一個(gè)是類類型或枚舉類型。
  2. 被重載操作符的操作數(shù)中至少有一個(gè)不是內(nèi)建類型,如int,char,double等及其指針或引用。
  3. 操作符的優(yōu)先級(jí)不會(huì)因其被重載而發(fā)生改變。
  4. 操作符的操作數(shù)個(gè)數(shù)不會(huì)因其被重載而發(fā)生改變。
  5. 除“()”之外的所有操作符都不能接受缺省參數(shù)。
  6. 并不是所有操作符都能被重載,如::、.*、.和?:,等等。

操作符標(biāo)記與操作符函數(shù)

  1. 將一個(gè)操作符標(biāo)記#應(yīng)用于一個(gè)或多個(gè)類類型的操作數(shù)時(shí),編譯器將調(diào)用與這個(gè)操作符標(biāo)記相關(guān)聯(lián)的操作符函數(shù)operator#()。
-----------+------------
操作符標(biāo)記 | 操作符函數(shù)
-----------+------------
         = | operator=
         + | operator+
        += | operator+=
        ++ | operator++
        << | operator<<
        [] | operator[]
       ... | ...
-----------+------------
  1. 操作符函數(shù)的重載定義通常包括全局函數(shù)和成員函數(shù)兩種形式。

輸入輸出操作符

  1. 一般而言,如果一個(gè)輸入輸出操作符#已經(jīng)按照全局函數(shù)的方式被重載定義了,那么表達(dá)式
    L#R
    將被編譯器解釋為如下函數(shù)調(diào)用:
    operator#(L,R)
    可見,按照全局函數(shù)方式被重載定義的輸入輸出操作符函數(shù),應(yīng)該有兩個(gè)參數(shù),分別是該操作符的左操作數(shù)和右操作數(shù)。
    范例:io_operator.cpp
  2. 為了能夠在操作符的全局函數(shù)重載定義中直接訪問類的私有成員,我們不妨將其聲明為該類的友元。
    范例:io_friend.cpp
  3. 友元聲明可以出現(xiàn)在一個(gè)類的私有、保護(hù)或公共部分,它允許被聲明者直接訪問該類的所有數(shù)據(jù)成員和成員函數(shù),無論其訪問控制屬性是私有的、保護(hù)的還是公共的。
    范例:friend.cpp

注意:重載輸入輸出操作符,重載的對(duì)象是std::cinstd::cout

std::basic_istream

std::basic_ostream

雙目操作符

  1. 一般而言,如果一個(gè)雙目操作符#已經(jīng)按照成員函數(shù)的方式被重載定義了,那么表達(dá)式,??
    L#R
    將被編譯器解釋為如下函數(shù)調(diào)用:
    L.operator#(R)
    可見,按照成員函數(shù)方式被重載定義的雙目操作符函數(shù),只有一個(gè)參數(shù),即該操作符的右操作數(shù)。而該操作符的左操作數(shù)將成為此成員函數(shù)形式操作符函數(shù)的調(diào)用對(duì)象。
    范例membinary.cpp

  2. 按照成員函數(shù)方式被重載定義的雙目操作符函數(shù),最終將被其左操作數(shù)所調(diào)用,且傳入其右操作數(shù)實(shí)參。因此,該操作符函數(shù)顯然應(yīng)該被定義為左操作數(shù)類型的成員函數(shù),且?guī)в幸粋€(gè)右操作數(shù)類型的形

  3. 輸出(或輸入)操作符左操作數(shù)的類型為ostream(或istream),因此我們即使能夠按照成員函數(shù)的方式為其提供重載定義,也應(yīng)該將其定義為ostream(或istream)的成員函數(shù),而我們無法為這個(gè)輸出(或輸入)流類自行添加新的成員函數(shù)。因此,我們別無選擇,只能對(duì)輸出(或輸入)操作符進(jìn)行全局重載定義。但是,我們?nèi)匀豢梢詫⑤敵?或輸入)操作符的全局重載定義聲明為被輸出(或輸入)對(duì)象類型的友元,以使它更接近于成員函數(shù)的本質(zhì)。

單目操作符

一般而言,如果一個(gè)單目操作符#已經(jīng)按照成員函數(shù)的方式被重載定義了,那么表達(dá)式:
#O
將被編譯器解釋為如下函數(shù)調(diào)用:
O.operator#()
可見,按照成員函數(shù)方式被重載定義的單目操作符函數(shù),沒有任何參數(shù)。而該操作符唯一的一個(gè)操作數(shù)將成為此成員函數(shù)形式的操作符函數(shù)的調(diào)用對(duì)象。
范例:memunary.cpp

自增自減操作符

++O ==> O.operator++()
O++ ==> O.operator++(0)
--O ==> O.operator--()
O-- ==> O.operator--(0)

注意:前綴操作符可以重復(fù)使用。
范例:memself.cpp

成員還是友元

  • 一個(gè)操作符的左右操作數(shù)不一定都是相同類型的對(duì)象,這就涉及到將該操作符函數(shù)定義為誰的成員,誰的友元的問題。

例如:
cin>>a
/*操作對(duì)象*//*操作符*//*被操作對(duì)象*/
/*需要重載的對(duì)象*//*需要重載的操作符*//*被操作對(duì)象*/

  • 一個(gè)操作符函數(shù)被聲明為哪個(gè)類的友元,取決于該函數(shù)參數(shù)對(duì)象的類型。

  • 一個(gè)操作符函數(shù)被定義為哪個(gè)類的成員,取決于該函數(shù)調(diào)用對(duì)象的類型。
    范例:friend2.cpp

類型轉(zhuǎn)換操作符與自定義類型轉(zhuǎn)換

  1. 通過類型轉(zhuǎn)換操作符可實(shí)現(xiàn)自定義類型轉(zhuǎn)換。類型轉(zhuǎn)換操作符只能被定義為源類型的成員函數(shù),而不能被定義為全局函數(shù)。當(dāng)需要進(jìn)行類型轉(zhuǎn)換時(shí)(構(gòu)造、賦值、函數(shù)調(diào)用等),編譯器將產(chǎn)生如下函數(shù)調(diào)用:
    obj.operator int ();
    范例:OperatorTypeConversion.cpp

  2. 通過構(gòu)造函數(shù)實(shí)現(xiàn)自定義類型轉(zhuǎn)換。以源類型對(duì)象為參數(shù),通過目標(biāo)類型中特定的構(gòu)造函數(shù),創(chuàng)建一個(gè)目標(biāo)類型的對(duì)象。
    范例:OperatorTypeConversion02.cpp

  3. 在源類型中定義類型轉(zhuǎn)換運(yùn)算符,同時(shí)為目標(biāo)類型提供以源類型對(duì)象為參數(shù)的構(gòu)造函數(shù),不同的類型轉(zhuǎn)換方式會(huì)有各自的匹配策略:通過類型轉(zhuǎn)換運(yùn)算符完成隱式類型轉(zhuǎn)換,通過構(gòu)造函數(shù)完成靜態(tài)類型轉(zhuǎn)換。
    范例:OperatorTypeConversion02.cpp

  4. 為具有類型轉(zhuǎn)換性質(zhì)的構(gòu)造函數(shù)添加explicit修飾符,表明此構(gòu)造函數(shù)僅支持顯式類型轉(zhuǎn)換。通過這種機(jī)制可有效地防止誤轉(zhuǎn)換。
    范例:OperatorTypeConversion03.cpp

  5. 為類型轉(zhuǎn)換運(yùn)算符函數(shù)添加explicit修飾符,表明此函數(shù)僅支持顯式類型轉(zhuǎn)換。通過這種機(jī)制可有效地防止誤轉(zhuǎn)換。
    范例:OperatorTypeConversion04.cpp
    說明:此特性要求編譯器支持C++0X標(biāo)準(zhǔn),g++ -std=c++11 OperatorTypeConversion04.cpp

解引用操作符(*和->)與智能指針

Smartptr.cppauto_ptr

函數(shù)操作符

Square.cpp

new/delete操作符

newdel.cpp
說明:此特性要求編譯器支持C++11標(biāo)準(zhǔn),g++ -std=c++11 newdel.cpp

參考:operator_newoperator_delete

最后編輯于
?著作權(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)容