C++ operator關鍵字

來源:互聯網
上載者:User

標籤:opera   private   針對   功能   ret   決定   建立   ring   分析   

operator是C++的關鍵字,它和運算子一起使用,表示一個運算子函數,理解時應將operator=整體上視為一個函數名。

   這是C++擴充運算子功能的方法,雖然樣子古怪,但也可以理解:一方面要使運算子的使用方法與其原來一致,另一方面擴充其功能只能通過函數的方式(c++中,“功能”都是由函數實現的)。

 

 一、為什麼使用操作符重載?
對於系統的所有操作符,一般情況下,只支援基礎資料型別 (Elementary Data Type)和標準庫中提供的class,對於使用者自己定義的class,如果想支援基本操作,比如比較大小,判斷是否相等,等等,則需要使用者自己來定義關於這個操作符的具體實現。比如,判斷兩個人是否一樣大,我們預設的規則是按照其年齡來比較,所以,在設計person 這個class的時候,我們需要考慮操作符==,而且,根據剛才的分析,比較的依據應該是age。那麼為什麼叫重載呢?這是因為,在編譯器實現的時候,已經為我們提供了這個操作符的基礎資料型別 (Elementary Data Type)實現版本,但是現在他的運算元變成了使用者定義的資料類型class,所以,需要使用者自己來提供該參數版本的實現。

 

二、如何聲明一個重載的操作符?
A:  操作符重載實現為類成員函數
重載的操作符在類體中被聲明,聲明方式如同普通成員函數一樣,只不過他的名字包含關鍵字operator,以及緊跟其後的一個c++預定義的操作符。
可以用如下的方式來聲明一個預定義的==操作符:
class person{
private:
    int age;
    public:
    person(int a){
       this->age=a;
    }
   inline bool operator == (const person &ps) const;
};
實現方式如下:
inline bool person::operator==(const person &ps) const
{

     if (this->age==ps.age)
        return true;
     return false;
}
調用方式如下:
#include
using namespace std;
int main()
{

  person p1(10);
  person p2(20);
  if(p1==p2) cout<<”the age is equal!”< return 0;
}
這裡,因為operator ==是class person的一個成員函數,所以對象p1,p2都可以調用該函數,上面的if語句中,相當於p1調用函數==,把p2作為該函數的一個參數傳遞給該函數,從而實現了兩個對象的比較。

B:操作符重載實現為非類成員函數(全域函數)
對於全域重載操作符,代表左運算元的參數必須被顯式指定。例如:
#include
#include
using namespace std;
class person
{
public:
int age;
public:
};

bool operator==(person const &p1 ,person const & p2)

//滿足要求,做運算元的類型被顯示指定
{
if(p1.age==p2.age)
return true;
return false;
}
int main()
{
person rose;
person jack;
rose.age=18;
jack.age=23;
if(rose==jack)
cout<<"ok"< return 0;
}

 

 

C:如何決定把一個操作符重載為類成員函數還是全域名字空間的成員呢?
①如果一個重載操作符是類成員,那麼只有當與他一起使用的左運算元是該類的對象時,該操作符才會被調用。如果該操作符的左運算元必須是其他的類型,則操作符必須被重載為全域名字空間的成員。
②C++要求賦值=,下標[],調用(), 和成員指向-> 操作符必須被定義為類成員操作符。任何把這些操作符定義為名字空間成員的定義都會被標記為編譯時間刻錯誤。
③如果有一個運算元是類類型如string類的情形那麼對於對稱操作符比如等於操作符最好定義為全域名字空間成員。

 


D:重載操作符具有以下限制:

(1) 只有C++預定義的操作符集中的操作符才可以被重載;

(2)對於內建類型的操作符,它的預定義不能被改變,應不能為內建類型重載操作符,如,不能改變int型的操作符+的含義;

(3) 也不能為內建的資料類型定義其它的操作符;

(4) 只能重載類類型或枚舉類型的操作符;

(5) 重載操作符不能改變它們的操作符優先順序;

(6) 重載操作符不能改變運算元的個數;

(7) 除了對( )操作符外,對其他重載操作符提供預設實參都是非法的;

 

 

E: 注意點
(1)後果載操操作符首先要確定它的傳回值是左值,還是右值,如果是左值最返回引用,如果是右值那就直接傳回值;

(2) +號等這樣的操作符沒有對象可以容納改變後值,對於這樣的情況最好返回數值,否則只能要操作符體內建立臨時對象用於容納改變後的值,如果在堆中建立臨時對象返回指標或者引用,在操作符函數體外還需要釋放它,如果返回的對象而不是引用或者指標,那麼效率是比較低的。如果返回的是數值,最好在該類的建構函式中增加對該類型數值的轉換函式,如:傳回值是int類型,那麼最好有一個int類型作為參數的建構函式。

(3)在遞增運算子中,放上一個整數形參,就是後增量運行符,它是值返回,對於前增量沒有形參,而且是引用返回,樣本:

class Test

{

    public:

    Test(x=3){ m_value = x}

    Test &operator ++();   //前增量

    Test &operator ++(int);//後增量

private:

    Int m_value:

};

Test &Test::operator ++()

{

    m_value ++;    //先增量

    return *this;  //返回當前對象

}

Test Test::operator ++(int)

{

    Test tmp(*this);  //建立臨時對象

    m_value ++;       //再增量

    return temp;      //返回臨時對象

}

(4)因為強制轉換是針對基礎資料型別 (Elementary Data Type)的,所以對類類型的轉換需自訂;

(5) 轉換運行符重載聲明形式:operator 類型名();它沒有傳回型別,因為類型名就代表了它的傳回型別,所以傳回型別顯得多餘。

(6)一般來說,轉換運算子與轉換建構函式(即帶一個參數的建構函式)是互逆的,如有了建構函式Test(int),那麼最好有一個轉換運算子int()。這樣就不必提供對象參數重載運算子了,如Test a1(1);Test a2(2); Test a3; a3 = a1+a2;就不需要重載+號操作符了,因為對於a1+a2的運算,系統可能會先找有沒有定義針對Test的+號操作符,如果沒有,它就會找有沒有針對Test類轉換函式參數類型的+號操作符(因為可以將+號運行結果的類型通過轉換函式轉換為Test對象),因為Test類有個int類型的參數,對於int類型有+操作符,所以a1+a2真正執行的是Test(int(a1) + int(a2));即Test(3);

(7)對於轉換運算子,還有一個需要注意的地方就是,如果A類中有以B為參數的轉換函式(建構函式),那B中不能有A的轉換運算子,不然就存在轉換的二義性,如:

class A{A(B&){…}}; class B{ operator A(){…}};那麼以下語句就會有問題:

B b; A(b);//A(b)有就可能是A的建構函式,也可以是B的轉換運算子

C++ operator關鍵字

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.