二級C++考點歸納:運算子過載
8.1 運算子函資料與運算子過載
運算子過載是計算機語言固有多型性的體現,是構成計算機語言的基礎之一。
C++把過載的運算子視為特殊的函式,稱為運算子函式。運算子過載就是函式過載的一種特殊情況。像對待一般過載函式一樣,編譯系統能夠依據使用運算子的不同環境,即引數(運算元)的數量或型別的差異,區分同一運算子的不同含義。
“運算子過載”是針對C++中原有運算子進行的,不可能通過過載創造出新的運算子。除了。、。*、->*、::、?:這五個運算子外,其他運算子都可以過載。由於很多符號是一元運算子和二元運算子公用的,為了避免含混,不得為過載的運算子函式設定預設值,呼叫時也就不得省略實參。
除了new和delete這兩個較為特殊運算子以外,任何運算子如果作為成員函式過載時不得過載為靜態函式。=、[ ]、()、->以及所有的型別轉換運算子只能作為成員函式過載,而且不能是針對列舉型別運算元的過載。
運算子函式的函式名是由運算子前加關鍵字operator構成的,在宣告運算子或呼叫運算子時都可以用這個名稱。
8.2 典範運算子的過載
1.?關於分數類fraction
fraction的宣告和定義包含在標頭檔案fraction.h和程式檔案中。
一個標準的用fraction表示的分數須滿足以下影印件:
①分母永遠為正,分數和符號用分子表示;
②分子分母互質,即總表示為最簡分數。
fraction通過兩個私有資料成員num和den分別儲存分子和分母,並在必要時呼叫standardize函式進行標準化處理,以使num和den的值滿足標準分數的條件。gcd是求兩個整數的最大公約數的函式,standardize在化簡分數時要呼叫它。
2.?過載取負運算子“-”
因為fraction用分子的符號代表整個分數的符號,因此所謂“取負”只需對分子num取負就可以了。由於取負運算子“-”是一元運算子,當作為成員函式過載時引數表中沒有引數,那個唯一的運算元以this指標的形式隱藏在引數表中。為此,只需要在fraction.h的類宣告中增加:
fraction poerator -()const { return fraction(-num,den);}
就可以了。由於在類宣告中直接給出了完整定義,因此是一個inline函式。
“-”是一個典型的一元運算子,除++、--外的其他一元運算子的過載都可以參考這裡描述的方法。
3.?過載加法運算子“+”
“ +”是一個二元運算子,因此作為成員函式過載時引數表中只有一個引數,對應於第二運算元,而第一運算元就是物件本身,僅以this指標的形式隱藏在參靈敏表中。
“+”是一個典型的二元運算子,除賦值類運算子外的其他二元運算子的過載都可以參考這裡描述的方法。
4.?過載增1運算子“+ +”
+ +既可以是字首運算子(前增1),又可以是字尾運算子(後增1)。為了區分這兩種情況,過載這兩個運算子時必須在格式上有所區別:過載字尾+ +時必須多一個虛擬引數:int,因此從形式上看像是一個二元運算子過載。
5.?過載型別轉換符“long”
型別轉換符必須作為成員函式過載。在過載型別轉換符時,由於運算子本身已經表示出返回值型別,因此不需要返回值型別的宣告。一個分數可以看成是由一個整數部分和一個純分數部分組成的,為了取得一個分數的整數部分,可為fraction過載型別轉換符long.為此可在fraction.h的類宣告中增加:
opertator long()const { return num/den;}
6.?過載賦值運算子“=”
賦值運算子只能作為成員函式過載。
常見的真正需要過載賦值運算子的'情況是:類中包含指向動態空間的指標
賦值運算子=的過載應注意以下幾點:
①返回值宣告為引用,而函式體中總是用語句return *this;返回;
②如果引數被宣告為指向同類物件的引用或指標,應判別所指向物件的是否與被賦值物件為同一物件,如果是,立即返回,不做任何賦值處理;
③如果被賦值物件佔用了動態空間或其他資源,應首先釋放這些資源,以便接收新的資源;
④如果引數被宣告為指標或引用,通常應加上const修飾;
⑤如果引數被宣告為指標,應判別是否為空,以便做出特殊處理;
⑥一個類如果需要過載運算子=,通常也就需要定義自己特有的拷貝建構函式,反之亦然。
7.?過載複合賦值運算子“+=”
過載複合賦值類運算子,如+=、-=等,也應遵循上述過載賦值運算子的注意事項。
與賦值運算子不同的是,複合賦值類運算子既可作為成員函式過載也可作為非成員函式過載。在後一種情況下,兩個運算元都必須出現在引數表中;為了保持運算子原有的特性,第一引數應當宣告為引用(否則就無法改變它的值),返回值也應當像過載“=”那樣宣告為引用,並在最後將獲得新值的第一引數返回。
8.?過載關係操作符“>”
過載的關係操作符函式應返回邏輯值。對於 fraction的兩個物件,可以通過比較通分後的兩個分子來確定它們的大小。為此,可在fraction.h的類宣告中增加如下的成員函式宣告:
bool operator>(fraction f){ return num*>*den;}
其他關係運算符可以參照過載。
9?過載下標訪問運算子“[ ]”
運算子[ ]只能作為成員函式過載。
10?過載C+ +流運算子“??”和“??”
C+ +流的輸入運算子??和輸出運算子??只能作為非類成員函式過載。在一個類中,如有必要,可將??或??宣告為友元函式。
8.3 運算子過載應注意的幾個問題
1.?過載的運算子應保持其原有的基本語義
過載的運算子應該體現為原運算子的功能在新的資料型別上的延伸,它的使用應當使程式中演算法的表達顯得更流暢、自然,使閱讀程式的人在不借助於其他說明資料的情況下就能夠正確理解。不要讓過載的運算子去勉強承擔那些更適於一般函式承擔的功能。