第14章 操作重載與類型轉換
但是如果對於一個運算符比如+號,既有重載的成員函數,又有重載的非成員函數,那麼此時如果直接使用+號,那麼就會出現錯誤. 因爲編譯器不知道要調用那個運算符.
2. 逗號,運算符 邏輯與&&運算符 邏輯或||運算符不建議重載.
因爲上述3種運算符本身是有求值順序和短路求值特性(&&和||有短路求值特性)的. 但是重載後的運算符本質上是一次函數調用, 所以求值順序和短路求值特性都會消失.
注意上面第一個a&&(v--)打印的是1而不是0. 就算你用()括住v--, v—這個表達式的返回值依然是v的原始值.
3. 賦值(=), 下標([]), 調用( () ), 成員訪問箭頭(->)的重載運算符函數必須定義爲類的成員函數(否則編譯不通過).
4. 重載的運算符的不同類型參數的順序不可改變.
因爲重載了A+int的運算符,所以a+v正確但是v+a是錯的.
但是下面的”111”和s卻可以任意調換順序?
因爲定義了的是非成員函數operator+(string,string),而不是operator+(const char*, string) 所以字符串常量會自動隱式轉化爲string對象.
5. 重載輸入輸出運算符>>和<<.
首先兩個運算符的os is 參數和返回值必須是非const的引用. 因爲流對象不可拷貝且會改變狀態.
其次對於輸入運算符>>,類的對象必須是非const引用. 對於輸出運算符<<,類的對象建議爲const 引用.
6. 相等運算符==與不等運算符!=
一般一個類定義了==運算符,那麼一般也要定義一個不等!=運算符.
且!=運算符只是調用==運算符來工作, 即只有一個運算符真正負責比較工作.
7. 可以給一個類定義多個重載的運算符。
8. 重載下標運算符[]
重載下標運算符[]首先應返回引用,其次一般定義const版本和非const版本兩個重載函數。
因爲b是常量,所以我們不能給b[2]賦值的。
9. 重載遞增++遞減--運算符。
首先,每種運算符建議重載前置和後置兩個版本。
其次,前置版本返回引用,後置版本返回值。
10. 重載*解引用和->成員訪問運算符。
注意:
*解引用返回對象的引用,->成員訪問運算符返回成員的地址。
->成員訪問運算符獲取成員這一事實永不變.
11. 類類型轉換
類類型轉換由:隱式轉換構造函數(單參數構造函數)和類型轉換運算符共同定義。
隱式轉換構造函數: 別的類型轉換爲當前類的類型。
類型轉換運算符: 當前類對象轉換爲其他類型。
類型轉換運算符無顯示返回類型,無形參,必須定義成類的成員函數。
12. 有二義性的類型轉換
情況一:假設現在要把B類型對象轉換爲A類型對象。且如果A中有參數爲B對象的構造函數且B中有目標對象爲A的類型轉換運算符,那麼從B->A時,既可以調用A的轉換構造函數,又可以調用B的轉換運算符,產生二義性。
情況二:如果類A存在與多個內置算術類型之間的轉換,那麼要小心。
情況三:假設func(Dd)和func(Cc)是兩個重載的函數。且D和C類對象都可以用int轉換得來,那麼func(10)調用將產生二義性。
結論:除了顯式的(explicit)向bool類型的轉換之外,應儘量避免定義類型轉換運算符和非顯式的轉換構造函數。