程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [More Effective C++]Item 5

[More Effective C++]Item 5

編輯:C++入門知識

Item 5: 對定制的“類型轉換函數”保持警覺         C++從C語言那繼承了其隱式轉換,可以實現不同類型之間的轉換,且C++的隱式轉換還存在更令人害怕的轉型,有可能出現數據丟失。對於這些,你無能為力,因為這都是語言自身提供的。然而當你的自定義類型登場時,你可以通過提供某些函數,來作為編譯器的轉型之用。但是為什麼最好不要提供任何類型轉換函數呢?     原因在於:在你為打算也為預期的情況下,此類函數可能會被調用,而其結果可能不正確、不直觀,很難調試。           在C++中,編譯器會通過兩種方式來實現類型的隱式轉換:     1、使用隱式類型轉換符,即關鍵詞operator之後加上一個類型名稱,如operator double(),注意:你不能為此函數指定返回值類型;     2、通過單變量的constructor,包括只有一個參數的constructor,也包括多個參數,但除了第一個參數外其他的參數都是有缺省值的constructor,如Constructor_Name(Type name)和Constructor_Name(Type1 name1,Type2 name2=Default_Value)。         下面我們來分別介紹這兩種方式別調用的調節以及應對措施:     第一種:使用operator重載函數     當為自定義類提供operator double()重載函數時,該重載函數會在以下情況被調用:ClassType temp(1,2);  double d=0.5*temp;     大概轉換過程是:對象temp調用operator double()轉換為double temp=1/2;然後與0.5相乘,最後把結果賦值給變量d。     這種情況比較好解決:我們只要以功能對等的另一個函數取代類型轉換操作符,如將operator double() 轉換為 double asDouble()即可。     這樣,當需要轉型時,需要顯示的調用該member function才能實現。        第二種:通過單變量constructor     通過單自變量constructor完成的隱式轉換較難消除。如下例所示:     template <class T>     class Array{     public:       Array(int size);       ...       T& operator[] (int index);     };     Array<int> a(10);     Array<int> b(10);     for(int i=0; i<10; i++) if(a == b[i]){do something ...} else {do other things...}     因為代碼中把a[i]寫成了a,編譯器原本應該給出錯誤或者警告提示的,但是C++編譯器很聰明,它會想盡辦法找到一個合適的函數以使程序順利執行,因此它發現只要將b[i]通過constructor就可以轉換為Array<int>類型的對象,於是它就放手去做了。     於是問題就出現了,循環的每次比較都發生在a的內容和一個大小為b[i]的臨時數組做比較,結果可想而知。且這樣做因為每次都要構造和析構一個臨時對象,所以十分沒效率。     那該怎麼解決呢?     1、如果你的編譯器支持explicit關鍵詞,就容易解決,只要將constructor做如下聲明即可;     explicit Constructor_Name(Type var);這樣編譯器就不會因隱式轉換而調用它了,不過顯式類型轉換仍是允許的哦。     2、如果你的編譯器不支持explicit關鍵詞,那麼只能走彎路,利用C++的規則中的一條:沒有任何一個轉換程序可以內含一個以上的“用戶定制轉換行為”。     我們可以將Array類的constructor進行變換,產生一個新類ArraySize類,該類只用於表明數組的大小。即     class Array {     public:       class ArraySize {       public:         ArraySize(int num):theSize(num);         ...       };     Array(ArraySize size);     }     如此一來,當我們定義Array類的對象時:Array<int> a(10);編譯器會發現可以利用ArraySize類的constructor實現int->ArraySize object的轉換,它毫不猶豫地做了,事實也證明這樣做是對的,Array類的constructor的確需要一個ArraySize類的object。對於這個情況是我們需要的隱式轉換,但是對於其他情況呢?     我們來看另一種情況,同上例,if(a == b[i]),我們將a[i]寫成了a,此時會不會發生隱式轉換呢?答案是否定的。     因為對於上面的情況,如果可以成功執行,需要兩個轉換:1)通過ArraySize類的constructor將int b[i]轉換為ArraySize的對象;2)再通過Array類的constructor將ArraySize類的對象轉換為Array<int>類型的對象。由C++規則可知,這樣的轉換程序是禁止的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved