More Effective C++ 條款21 (轉)
條款21:透過過載避免隱式型別轉換:namespace prefix = o ns = "urn:schemas--com::office" />
以下是一段程式碼,如果沒有什麼不尋常的原因,實在看不出什麼東西:
class UPInt { // unlimited precision
public: // integers 類
UPInt();
UPInt(int value);
...
};
//有關為什麼返回值是const的解釋,參見Effective C++ 條款21
const UPInt operator+(const UPInt& lhs, const UPInt& rhs);
UPInt upi1, upi2;
...
UPInt upi3 = upi1 + upi2;
這裡還看不出什麼令人驚訝的東西。upi1 和upi2都是UPInt,所以它們之間相加就會UPInts的operator。
現在考慮下面這些語句:
upi3 = upi1 + 10;
upi3 = 10 + upi2;
這些語句也能夠成功執行。方法是透過建立臨時物件把整形數10轉換為UPInts(參見條款19)。
讓完成這種型別轉換是確實是很方便,但是建立臨時物件進行型別轉換工作是有開銷的,而我們不想承擔這種開銷。就象大多數人只想從政府那裡受益而不想為此付出一樣,大多數C++員希望進行沒有臨時物件開銷的隱式型別轉換。但是在計算領域裡發生不了赤字現象,我們如何能這麼做呢?
讓我們回退一步,認識到我們的目的不是真的要進行型別轉換,而是用UPint和int做為引數呼叫operator。隱式型別轉換隻是用來達到目的的手段,但是我們不要混淆手段與目的。還有一種方法可以成功進行operator的混合型別呼叫,它將消除隱式型別轉換的需要。如果我們想要把UPInt和int物件相加,透過宣告如下幾個函式達到這個目的,每一個函式有不同的引數型別集。
const UPInt operator+(const UPInt& lhs, // add UPInt
const UPInt& rhs); // and UPInt
const UPInt operator+(const UPInt& lhs, // add UPInt
int rhs); // and int
const UPInt operator+(int lhs, // add int and
const UPInt& rhs); // UPInt
UPInt upi1, upi2;
...
UPInt upi3 = upi1 + upi2; // 正確,沒有由upi1 或 upi2
// 生成的臨時物件
upi3 = upi1 + 10; // 正確, 沒有由upi1 or 10
// 生成的臨時物件
upi3 = 10 + upi2; //正確, 沒有由10 or upi2
//生成的臨時物件。
一旦你開始用函式過載來消除型別轉換,你就有可能這樣宣告函式,把自己陷入危險之中:
const UPInt operator+(int lhs, int rhs); // 錯誤!
這個想法是合情合理的。對於UPInt和int型別,我們想要用所有可能的組合來過載operator函式。上面只給出了三種過載函式,唯一漏掉的是帶有兩個int引數的operator,所以我們想把它加上。
有道理麼?在C++中有一條規則是每一個過載的operator必須帶有一個定義型別(user-defined type)的引數。int不是使用者定義型別,所以我們不能過載operator成為僅帶有此型別引數的函式。(如果沒有這條規則,程式設計師將能改變預定義的操作,這樣做肯定把程式引入混亂的境地。比如企圖過載上述的operator,將會改變int型別相加的含義。)
利用過載避免臨時物件的方法不只是用在operator函式上。比如在大多數程式中,你想允許在所有能使用string物件的地方,也一樣可以使用char*,反之亦然。同樣如果你正在使用numerical(數字)類,例如complex(參見條款35),你想讓int和double這樣的型別可以使用在numerical物件的任何地方。因此任何帶有string、char*、complex引數的函式可以採用過載方式來消除型別轉換。
不過,必須謹記80-20規則(參見條款16)。沒有必要實現大量的過載函式,除非你有理由確信程式使用過載函式以後其整體會有顯著的提高。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990982/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Effective C++ 條款08_不止於此C++
- Effective Modern C++ 系列之 條款2: autoC++
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- [讀書筆記][effective C++]條款30-inline的原理筆記C++inline
- 文獻學習——Making Deduction More Effective in SAT Solvers
- 學懂現代C++——《Effective Modern C++》之轉向現代C++C++
- effective C++ : CHAPTER 8C++APT
- 【Effective Modern C++】索引C++索引
- Effective C++筆記C++筆記
- effective C++筆記1C++筆記
- 《Effective C++》讀書筆記C++筆記
- Effective C++ 筆記(3)資源管理C++筆記
- Effective C++ 4.設計與宣告C++
- 條款01: 視C++為一個語言聯邦C++
- 《Effective C++》閱讀總結(三):資源管理C++
- 《Effective C++》第三版-1. 讓自己習慣C++(Accustoming Yourself to C++)C++
- 學懂現代C++——《Effective Modern C++》之型別推導和autoC++型別
- 條款05: 瞭解c++默默編寫並呼叫哪些函式C++函式
- 《Effective C++》第三版-5. 實現(Implementations)C++
- 讀完Java名著《Effective Java》: 我整理了這50條技巧Java
- “21天教你學會C++”C++
- 《Effective C++》閱讀總結(四): 設計、宣告與實現C++
- 21天學通C++(C++程式的組成部分)C++
- 《Effective C++》第三版-3. 資源管理(Resource Management)C++
- c++切面條題目C++
- 軟體開發的21條規律
- 《Effective C++》第三版-4. 設計與宣告(Design and Declarations)C++
- 《Effective Python 第二版》第二條 遵循PEP8風格指南Python
- “21天教你學會C++”,不要太在意~C++
- MySQL效能優化的最佳21條經驗MySql優化
- 《Effective C++》閱讀總結(二):類的構造、析構和賦值C++賦值
- 《看雪服務條款》
- 【C++】C++之型別轉換C++型別
- C++中的條件變數C++變數
- MORE_DETAIL_TECHAI
- TypeScript 之 More on FunctionsTypeScriptFunction
- More web function requests go online concurrently, and web service deployment is faster and more economical!WebFunctionGoAST
- effective java 觀後感Java
- DNS: More than just namesDNS