C++ operator關鍵字(重載操做符)

operator是C++的關鍵字,它和運算符一塊兒使用,表示一個運算符函數,理解時應將operator=總體上視爲一個函數名。    這是C++擴展運算符功能的方法,雖然樣子古怪,但也能夠理解:一方面要使運算符的使用方法與其原來一致,另外一方面擴展其功能只能經過函數的方式(c++中,「功能」都是由函數實現的)。    1、爲何使用操做符重載? 對於系統的全部操做符,通常狀況下,只支持基本數據類型和標準庫中提供的class,對於用戶本身定義的class,若是想支持基本操做,好比比較大小,判斷是否相等,等等,則須要用戶本身來定義關於這個操做符的具體實現。好比,判斷兩我的是否同樣大,咱們默認的規則是按照其年齡來比較,因此,在設計person 這個class的時候,咱們須要考慮操做符==,並且,根據剛纔的分析,比較的依據應該是age。那麼爲何叫重載呢?這是由於,在編譯器實現的時候,已經爲咱們提供了這個操做符的基本數據類型實現版本,可是如今他的操做數變成了用戶定義的數據類型class,因此,須要用戶本身來提供該參數版本的實現。   2、如何聲明一個重載的操做符? 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)由於強制轉換是針對基本數據類型的,因此對類類型的轉換需自定義; (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的轉換運算符
相關文章
相關標籤/搜索