MOOC C++筆記(四):運算符重載

第四周:運算符重載

基本概念

運算符重載,就是對已有的運算符(C++中預定義的運算符)賦予多重的含義,使同一運算符作用於不同類型的數據時導致不同類型的行爲。
運算符重載的目的是:擴展C++中提供的運算符的適用範圍,使之能作用於對象。
同一個運算符,對不同類型的操作數,所發生的行爲不同。

運算符重載的形式

1.運算符重載的實質是函數重載。
2.可以重載爲普通函數,也可以重載爲成員函數。
3.把含運算符的表達式轉換成對運算符函數的調用。
4.把運算符的操作數轉換成運算符函數的參數。
5.運算符被多次重載時,根據實參類型決定調用哪個運算符函數。
返回值類型 operator 運算符(形參表)
{....
}
注意:重載爲成員函數是,參數個函數爲運算符目數減一。
重載爲普通函數時,參數個數爲運算符目數。

運算符重載爲友元函數

一般情況下,將運算符重載爲類的成員函數,是較好的選擇。
但有時,重載爲成員函數不能滿足使用要求,重載爲普通函數,又不能訪問類的私有成員,所以需要將運算符重載爲友元。
如加號的重載,使用時必須要保證對象在符號左側,這顯然與原有的符號有一定不同。
因此我們可以把+重載爲普通函數。同時將其設爲要訪問成員的友元。

賦值運算符的重載

有時候我們希望賦值運算符兩邊的類型可以不匹配,比如,把一個int類型變量賦值給一個Complex對象,或把一個char *類型字符串賦值給一個字符串對象,此時就需要重載賦值運算符“=“。
賦值運算符“=”只能重載爲成員函數。 爲什麼有的操作符重載函數只能是成員函數?
注意:初始化時調用的是複製構造函數,而不是運算符“=”:

string s="hello" //調用複製構造函數。
string s1("hello") //調用複製構造函數。
s="world" //調用運算符“=”。

淺拷貝與深拷貝

淺拷貝只是單純的把兩個對象的內容一致,並不能保證兩個對象的成員指向的不同的地址,如果對象中的成員是地址,那麼很容易造成兩個對象的成員指向同一個地址。這種賦值我們稱爲淺拷貝,淺拷貝往往是不安全的。
深拷貝保證兩個對象的地址指向的內容一致,而不是對象的地址一致。
對象缺省的賦值運算符一般執行淺拷貝,所以一般情況下我們要自己重載賦值構造函數。(對象的複製構造函數也是如此)
關於淺拷貝深拷貝以及重載賦值運算符需要注意的問題詳見:=運算符重載應注意點
關於賦值運算符重載的返回值類型:
對運算符進行重載的是後,好的風格是應該儘量保留運算符原本的特性
爲了支持這一特性並且支持a=b=c和(a=b)=c我們應該使用賦值左邊的對象的引用作爲返回類型。

流插入運算符的重載

iostream中重載了<>運算符,其中有istream對象與ostream對象。
爲了能支持連續運算,流運算符需要返回相應引用。
重載<>運算符只能使用普通函數,因爲iostrem對象已經在頭文件中完成,無法再爲它添加新的成員。

類型轉換運算符的重載

任何類型的名字都是一個類型轉換運算符(自定義類型?),其返回值都是本身的類型,比如double類型轉換運算符的返回類型就是double本身。
如:

operator double(){ //注意該類型轉化運算符是成員函數,
return real;
}

自增、自減運算符的重載

自增運算符++、自減運算符--有前置/後置之分,爲了區分所重載的是前置運算符還是後置運算符,C++規定:
前置運算符作爲一元運算符重載,後置運算符爲二元運算符除了類型本身還有一個int。
後置自增自減運算符返回類型爲該對象改變前的實體。
前置返回的是對象改變後的引用。
一般來說前置運算符比後置運算符要快很多,因爲後置運算符需要返回實體開銷較大。

關於運算符重載的其他注意點 :

1.C++不允許定義新的運算符;
2.重載後運算符的含義應該符合日常習慣;
3.運算符重載不改變運算符的優先級;
4.以下運算符不能重載:"."、".*"、"::"、"?:"、sizeof;
5.重載運算符()、[]、->或者賦值運算符,運算符重載函數必須聲明爲類的成員函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章