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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- More Effective C++ 條款4 (轉)C++
- More Effective C++ 條款19 (轉)C++
- More Effective C++ 條款6 (轉)C++
- More effective C++ 條款14 (轉)C++
- More Effective C++ 條款15 (轉)C++
- More Effective C++ 條款2 (轉)C++
- More Effective C++ 條款3 (轉)C++
- More Effective C++ 條款11 (轉)C++
- More effective C++ 條款13 (轉)C++
- More effective C++ 條款12 (轉)C++
- More Effective C++ 條款5 (轉)C++
- More Effective C++ 條款一 (轉)C++
- More Effective C++ 條款17 (轉)C++
- More Effective C++ 條款18 (轉)C++
- More Effective C++ 條款20 (轉)C++
- More Effective C++ 條款22 (轉)C++
- More Effective C++ 條款23 (轉)C++
- More Effective C++ 條款24 (轉)C++
- More Effective C++ 條款25 (轉)C++
- More Effective C++ 條款7 (轉)C++
- More Effective C++ 條款8 (轉)C++
- More Effective C++ 條款28(中) (轉)C++
- More effective c++ 條款10(上) (轉)C++
- More effective c++ 條款10(下) (轉)C++
- More Effective C++ 條款27(下) (轉)C++
- More Effective C++ 條款28(上) (轉)C++
- More Effective C++ 條款28(下) (轉)C++
- More Effective C++ 條款26(下) (轉)C++
- Effective C++: Item 21 (轉)C++
- Effective Modern C++ 系列之 條款2: autoC++
- Effective C++ 條款08_不止於此C++
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- [讀書筆記][effective C++]條款30-inline的原理筆記C++inline
- Effective C++: Item 32 (轉)C++
- Effective C++: Item 24 (轉)C++
- more effective entity bean(新的改進entity bean的效能的七條(EJB2.0版)) (轉)Bean
- Effective STL之條款2:謹防容器無關程式碼的假象 (轉)
- 《More Effective C#》讀書筆記C#筆記