運算符重載使自定義類的對象能像內(nèi)置類型的變量一樣使用內(nèi)置的運算符淳衙,擴充運算符的功能幅慌,增強了C++ 語言的可擴充性疮薇。
注意點:
- 不是所有的運算符都能重載
- 重載不能改變運算符的優(yōu)先級和結合性
- 重載不能改變運算符的操作數(shù)個數(shù)
- 不能創(chuàng)建新的運算符
運算符重載的方法
C++中規(guī)定嚎花,重載函數(shù)名為operator@
悼瘾,其中龟再,@
為要重載的運算符书闸。如要重載+
運算符,該重載函數(shù)名為operator+
利凑。
函數(shù)原型
運算符的重載不能改變運算符的運算對象數(shù)浆劲。因此,重載函數(shù)的形式參數(shù)個數(shù)(包括成員函數(shù)的隱式指針this)與運算符的運算對象數(shù)相同 哀澈。
運算符重載可以重載成成員函數(shù)也可以重載成全局函數(shù)實現(xiàn)牌借。重載成全局函數(shù)時,最好把此函數(shù)設為友員函數(shù)割按。
如果作為類的成員函數(shù)膨报,它的形式參數(shù)個數(shù)比運算符的運算對象數(shù)少1。這是因為成員函數(shù)有一個隱含的參數(shù)this适荣。在C++中现柠,把隱含參數(shù)this作為運算符的第一個參數(shù)。
所以當把一個一元運算符重載成成員函數(shù)時弛矛,該函數(shù)沒有形式參數(shù)够吩。把一個二元運算符重載成成員函數(shù)時,該函數(shù)只有一個形式參數(shù)汪诉,就是右操作數(shù)废恋,當前對象是左操作數(shù)。
全局函數(shù) vs成員函數(shù)
大多數(shù)運算符都可以重載成成員函數(shù)或全局函數(shù)扒寄。
賦值=
鱼鼓、下標[]
、函數(shù)調(diào)用()
和成員訪問->
必須重載成成員函數(shù)该编。
具有賦值意義的運算符迄本,如復合的賦值運算符以及++和--,不一定非要定義為成員函數(shù)课竣,但最好定義為成員函數(shù)嘉赎。
具有兩個運算對象的運算符最好重載為全局函數(shù)置媳,這樣可以使得應用更加靈活。如果把加運算定義成全局函數(shù)公条,r是有理數(shù)類的對象拇囊,則2+r是一個合法的表達式。
特殊的運算符的重載
賦值運算符
一般情況下靶橱,缺省的賦值運算符重載函數(shù)能滿足用戶的需求寥袭。但是,當類含有類型為指針的數(shù)據(jù)成員時关霸,可能會帶來一些麻煩传黄。
賦值運算符只能重載成成員函數(shù),函數(shù)原型為:
class &class::operator=(const class &tight)
{...}
一般來講队寇,需要拷貝構造函數(shù)的類也需要重載賦值運算符膘掰。定義對象時給對象賦初值調(diào)用的是拷貝構造函數(shù),程序的語句部分中的賦值語句調(diào)用的是賦值運算符重載函數(shù)佳遣。
下標運算符
下標運算符是二元運算符识埋,第一個運算數(shù)是數(shù)組名,第二個運算數(shù)是下標值苍日,下標運算符必須重載成成員函數(shù)惭聂。
函數(shù)原型為:
class & class::operator[](int index)
{...}
函數(shù)調(diào)用運算符
函數(shù)調(diào)用運算符()
是一個二元運算符。它的第一個運算對象是函數(shù)名相恃,第二個參數(shù)是形式參數(shù)表。運算的結果是函數(shù)的返回值笨觅。
一個類重載了函數(shù)調(diào)用運算符拦耐,就可以把這個類的對象當做函數(shù)來使用
函數(shù)調(diào)用運算符必須重載成成員函數(shù),函數(shù)原型為:
函數(shù)的返回值 operator() (形式參數(shù)表)见剩;
++和—運算符的重載
++
杀糯、--
是一元操作符,這兩個操作符可以是前綴苍苞,也可以是后綴固翰。而且前綴和后綴的含義是有區(qū)別的。所以羹呵,必須有兩個重載函數(shù)骂际。
但兩個重載函數(shù)有相同的原型,區(qū)分方法在于:前綴:一元操作符冈欢。后綴:二元操作符歉铝。
作為成員函數(shù)重載:
++ob重載為:class &class::operator++()
ob-- 重載為:class class::operator--(int)
作為友元函數(shù)重載:
++ob重載為:operator++(class &ob)
ob--重載為:operator--(class &ob,int)
int
沒有值的意義,僅僅起到區(qū)分作用凑耻,調(diào)用時太示,參數(shù)int一般傳遞給值0柠贤。
輸入輸出運算符重載
借助于流插入運算符>>
和流提取運算符<<
輸入和輸出用戶自定義類的對象。
輸入輸出運算符必須被重載成全局函數(shù)
輸入輸出運算符是二元運算符类缤,返回的是第一個對象的引用臼勉。由于第一個參數(shù)是輸入輸出流對象,只能重載為友元函數(shù)餐弱。
輸出運算符的重載
ostream & operator<<(ostream & os, const class &obj)
{
os<< ....;
return os;
}
輸入輸出運算符重載
istream & operator>>(istream & is, class &obj)
{
is >> ....;
return is;
}
重載函數(shù)的原型設計考慮
參數(shù)設計
對于任何函數(shù)的參數(shù)坚俗,如果僅需要從參數(shù)中讀,而不改變它岸裙,一般用const引用來傳遞猖败。
只有會修改左值參數(shù)的運算符,如賦值運算符降允,左值參數(shù)不是常量恩闻,所以用地址傳遞。
返回值的類型設計
運算符的結果產(chǎn)生一個新值剧董,就需要產(chǎn)生一個作為返回值的新對象幢尚。
對于邏輯運算符,人們希望至少得到一個int或bool的返回值翅楼。
所有的賦值運算符(如尉剩,=,+=等)均改變左值毅臊,應該能夠返回一個剛剛改變了的左值的非常量引用理茎。
自定義類型轉換運算符
內(nèi)置類型到類類型的轉換
利用構造函數(shù)進行轉換。例如管嬉,對于Rational類的對象r皂林,可以執(zhí)行r=2。 此時蚯撩,編譯器隱式地調(diào)用Rational的構造函數(shù)础倍,傳給它一個參數(shù)2。構造函數(shù)將構造出一個num=2胎挎,den= 1的Rational類的對象沟启,并將它賦給r。
explicit構造函數(shù)
任何單參數(shù)的構造函數(shù)都可以被編譯器用來執(zhí)行隱式轉換犹菇,即把內(nèi)置類型轉換成對應的類類型德迹。
在某些情況下,隱式轉換是不受歡迎的项栏。
將單參數(shù)的構造函數(shù)定義為explicit浦辨,將告訴編譯器不允許執(zhí)行隱式轉換。
如將Ratioanal類的構造函數(shù)定義成
explicit Rational(int n1 = 0, int n2 = 1)
則對于Rational類的對象r1和r2,執(zhí)行r1 = 2 + r2流酬;編譯器就會報錯币厕。
類類型到其它類型的轉換
可以通過類型轉換函數(shù)實現(xiàn),類型轉換函數(shù)必須重載成成員函數(shù)芽腾。
類型轉換函數(shù)的格式:
operator type() const
{
return (結果為目標類型的表達式);
}
類型轉換函數(shù)的特點:無參數(shù)旦装,無返回值,是const函數(shù)摊滔。
有了這個函數(shù)阴绢,我們可以將一個Rational類的對象r賦給一個type類型的變量x。如r的值為(1艰躺,3)呻袭,經(jīng)過賦值double x = r后,x的值為0.333333腺兴。