More Effective C++ 條款21 (轉)

worldblog發表於2007-12-10
More Effective C++ 條款21 (轉)[@more@] 

條款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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章