運算子多載
所謂重載,就是重新賦予新的含義。函數重載就是對一個已有的函數賦予新的含義,使之實現新功能,因此,一個函數名就可以用來代表不同功能的函數,也就是”一名多用”。
運算子也可以重載。實際上,我們已經在不知不覺之中使用了運算子多載。例如,大 家都已習慣於用加法運算子”+”對整數、單精確度數和雙精確度數進行加法運算,如5+8, 5.8 +3.67等,其實電腦對整數、單精確度數和雙精確度數的加法操作過程是很不相同的, 但由於C++已經對運算子”+”進行了重載,所以就能適用於int, float, doUble類型的運算。
C++中預定義的運算子的操作對象只能是基礎資料型別 (Elementary Data Type)。但實際上,對於許多使用者自訂類型(例如類),也需要類似的運算操作。這時就必須在C++中重新定義這些運算子,賦予已有運算子新的功能,使它能夠用於特定類型執行特定的操作。運算子多載的實質是函數重載,它提供了C++的可擴充性,也是C++最迷人的特性之一。
運算子多載是通過建立運算子函數實現的,運算子函數定義了重載的運算子將要進行的操作。運算子函數的定義與其他函數的定義類似,惟一的區別是運算子函數的函數名是由關鍵字operator和其後要重載的運算子符號構成的。運算子函數定義的一般格式如下:
<傳回型別說明符> operator <運算子符號>(<參數表>)
{ <函數體>}
運算子多載時要遵循以下規則:
(1) 除了類屬關係運算子"."、成員指標運算子".*"、範圍運算子"::"、sizeof運算子和三目運算子"?:"以外,C++中的所有運算子都可以重載。
(2) 重載運算子限制在C++語言中已有的運算子範圍內的允許重載的運算子之中,不能建立新的運算子。
(3) 運算子多載實質上是函數重載,因此編譯器對運算子多載的選擇,遵循函數重載的選擇原則。
(4) 重載之後的運算子不能改變運算子的優先順序和結合性,也不能改變運算子運算元的個數及文法結構。
(5) 運算子多載不能改變該運算子用於內部類型對象的含義。它只能和使用者自訂類型的對象一起使用,或者用於使用者自訂類型的對象和內部類型的對象混合使用時。
(6) 運算子多載是針對新類型資料的實際需要對原有運算子進行的適當的改造,重載的功能應當與原有功能相類似,避免沒有目的地使用重載運算子。
運算子函數重載一般有兩種形式:重載為類的成員函數和重載為類的非成員函數。非成員函數通常是友元。(可以把一個運算子作為一個非成員、非友元函數重載。但是,這樣的運算子函數訪問類的私人和保護成員時,必須使用類的公有介面中提供的設定資料和讀取資料的函數,調用這些函數時會降低效能。可以內聯這些函數以提高效能。)
成員函數運算子
運算子多載為類的成員函數的一般格式為:
<函數類型> operator <運算子>(<參數表>) { <函數體> }
當運算子多載為類的成員函數時,函數的參數個數比原來的運算元要少一個(後置單目運算子除外),這是因為成員函數用this指標隱式地訪問了類的一個對象,它充當了運算子函數最左邊的運算元。因此:
(1) 雙目運算子多載為類的成員函數時,函數只顯式說明一個參數,該形參是運算子的右運算元。
(2) 前置單目運算子多載為類的成員函數時,不需要顯式說明參數,即函數沒有形參。
(3) 後置單目運算子多載為類的成員函數時,函數要帶有一個整型形參。
調用成員函數運算子的格式如下:
<對象名>.operator <運算子>(<參數>)
它等價於
<對象名><運算子><參數>
例如:a+b等價於a.operator +(b)。一般情況下,我們採用運算子的習慣表達方式。
友元函數運算子
運算子多載為類的友元函數的一般格式為:
friend <函數類型> operator <運算子>(<參數表>) { <函數體> }
當運算子多載為類的友元函數時,由於沒有隱含的this指標,因此運算元的個數沒有變化,所有的運算元都必須通過函數的形參進行傳遞,函數的參數與運算元自左至右一一對應。
調用友元函數運算子的格式如下:
operator <運算子>(<參數1>,<參數2>)
它等價於
<參數1><運算子><參數2>
例如:a+b等價於operator +(a,b)。
兩種重載形式的比較
在多數情況下,將運算子多載為類的成員函數和類的友元函數都是可以的。但成員函數運算子與友元函數運算子也具有各自的一些特點:
(1) 一般情況下,單目運算子最好重載為類的成員函數;雙目運算子則最好重載為類的友元函數。
(2) 以下一些雙目運算子不能重載為類的友元函數:=、()、[]、->。
(3) 類型轉換函式只能定義為一個類的成員函數而不能定義為類的友元函數。
(4) 若一個運算子的操作需要修改對象的狀態,選擇重載為成員函數較好。
(5) 若運算子所需的運算元(尤其是第一個運算元)希望有隱式類型轉換,則只能選用友元函數。
(6) 當運算子函數是一個成員函數時,最左邊的運算元(或者只有最左邊的運算元)必須是運算子類的一 個類對象(或者是對該類對象的引用)。如果左邊的運算元必須是一個不同類的對象,或者是一個內部 類型的對象,該運算子函數必須作為一個友元函數來實現。
(7) 當需要重載運算子具有可交換性時,選擇重載為友元函數。
1 為什麼會用運算子多載機制(回憶函數重載)
用複數類舉例 //Complex c3 =c1 + c2;
//原因 Complex是使用者自訂類型,編譯器根本不知道如何進行加減
//編譯器給提供了一種機制,讓使用者自己去完成,自訂類型的加減操作。。。。。
//這個機制就是運算子多載機制
2 運算子多載的本質是一個函數
例如1:
//通過類成員函數完成 - 操作符重載(函數的定義在類裡面)//函式宣告 Complex operator-(Complex &c2)//用類成員函數實現-運算子多載Complex c4 = c1 - c2; c4.printCom(); //列印輸出//c1.operator-(c2);
例如2:
//通過全域函數方法完成+操作符重載(函數的定義在類外)//函式宣告 Complex operator+(Complex &c1, Complex &c2)//函數調用分析int main(){ Complex c1(1, 2), c2(3, 4);//定義兩個對象//Complex c31 = operator+(c1,c2); 函數的調用模式Complex c3 = c1 + c2; //簡寫+c3.printCom();}
感受操作過程:
例如3:
//前置++操作符 用全域函數實現Complex& operator++(Complex&c1) { c1.a ++; c1.b ++;return c1; }//調用方法++c1 ; //=è需要寫出操作符重載函數原形c1.printCom();//運算子多載函數名定義//首先承認操作符重載是一個函數 定義函數名--->operator++//分析函數參數 根據左右運算元的個數------->operator++(Complex &c1)//分析函數傳回值-------> Complex&operator++(Complex &c1) 返回它自身
例如4
//4.1 前置—操作符成員函數實現Complex& operator--(){ this->a--;this->b--;return *this; //注意返回}//4.2 調用方法--c1;c1.printCom();//4.3前置—運算子多載函數名定義//c1.operator--()
例如5:
//5.1//後置++ 操作符用全域函數實現Complex operator++(Complex &c1, int) { Complex tmp = c1;c1.a++;c1.b++;return tmp;}//5.2 調用方法c1 ++ ; //先使用後++//5.3 後置++運算子多載函數名定義Complex operator++(Complex&c1, int) //函數佔位參數 和 前置++ 相區別
例如6:
//6.1 後置— 操作符 用類成員函數實現Complexoperator--(int) { Complextmp = *this;this->a--;this->b--;return tmp;}//6.2 調用方法c1 ++ ; //先使用後++//6.3 後置--運算子多載函數名定義Complex operator--(int) //函數佔位參數和 前置-- 相區別
前置和後置運算子總結
C++中通過一個佔位參數來區分前置運算和後置運算
定義運算子多載函數名的步驟
全域函數、類成員函數方法實現運算子多載步驟
1)要承認操作符重載是一個函數,寫出函數名稱operator+ ()
2)根據運算元,寫出函數參數
3)根據業務,完善函數傳回值(看函數是返回引用 還是指標 元素),及實現函數業務
友元函數實現操作符重載的應用情境
1)友元函數和成員函數選擇方法 Ø 當無法修改左運算元的類時,使用全域函數進行重載Ø =, [], ()和->操作符只能通過成員函數進行重載2)用友元函數重載 << >>操作符Ø istream 和 ostream 是 C++ 的預定義流類 Ø cin 是 istream 的對象,cout 是 ostream 的對象Ø 運算子 << 由ostream 重載為插入操作,用於輸出基本類型資料Ø 運算子 >> 由 istream 重載為提取操作,用於輸入基本類型資料Ø 用友員函數重載 << 和 >> ,輸出和輸入使用者自訂的資料類型a)用全域函數方法實現 << 操作符 ostream& operator<<(ostream &out, Complex &c1){ //out<<"12345,生活真是苦"<<endl;out<<c1.a<<"+ "<<c1.b<<"i "<<endl;return out;}//調用方法cout<<c1;//鏈式編程支援cout<<c1<<"abcc";//cout.operator<<(c1).operator<<("abcd");//函數傳回值充當左值 需要返回一個引用b)類成員函數方法無法實現 <<操作符重載//因拿到cout這個類的源碼//cout.operator<<(c1);3) 友元函數重載操作符使用注意點a) 友員函數重載運算子常用於運算子的左右運算元類型不同的情況b)其他Ø 在第一個參數需要隱式轉換的情形下,使用友員函數重載運算子是正確的選擇Ø 友員函數沒有 this 指標,所需運算元都必須在參數表顯式聲明,很容易實作類別型的隱式轉換Ø C++中不能用友員函數重載的運算子有= () [] ->
請問:為什麼運演算法重載成員函數只有一個參數,而友元函數有兩個?
由於成員函數有指向對象的this指標,可以通過對象傳遞參數;而友元函數沒有this指標,所以必須要兩個參數。(針對二元操作符重載而言)
以上就是c++複習要點總結之七——運算子多載的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!