1. 程式人生 > >[C++]隱式類型別轉換(轉)

[C++]隱式類型別轉換(轉)

C++ primer 中有這麼一句話:可以用單個實參來呼叫的建構函式定義了從形參型別到該型別的一個隱式轉換。
這麼解釋:
比如有個類A的物件a的成員函式的引數應該是類A的物件,但是把一個別的型別B的物件b傳進去了,而且這個物件b的型別恰好是A的單引數建構函式引數型別,這時系統就用這個b自作聰明的建立了一個類A的臨時物件c,雖然c和a都是A型別,但是是不同的物件。
這種隱式轉換有很大風險,可以用explicit加在單引數建構函式前來避免這種類類隱形轉換。
我個人認為這就是一種人為使用錯誤,而編譯器又恰恰沒有指出。
本來應該A.a(A(b)),憑什麼用成A.a(b)?哈哈……


#include <string>
#include <iostream> using namespace std; class Fruit //定義一個類,名字叫Fruit { string name;//定義一個name成員 string colour;//定義一個colour成員 public: bool isSame(const Fruit& otherFruit)//期待的形參是另一個Fruit類物件,測試是否同名 { return name == otherFruit.name; } void print()//定義一個輸出名字的成員print()
{ cout << colour << " " << name << endl; } Fruit(const string& nst, const string& cst = "green"):name(nst), colour(cst){} Fruit(){} }; int main() { Fruit apple("apple"); Fruit orange("orange"); cout << "apple = orange? : "
<< apple.isSame(orange) << endl; //隱式轉換 cout << "apple = /"apple/"? :" << apple.isSame(string("apple")) << endl; return 0; }

你會發現最後的使用上,我們用一個string型別作一個期待Fruit類形參的函式的引數,結果竟然得出了是true(1),不要感到奇怪,這就是我現在要講的東西,隱式類型別轉換:“可以用單個實參來呼叫的建構函式定義了從形參型別到該型別的一個隱式轉換。”(C++ Primer)
首先要單個實參,你可以把建構函式colour的預設實參去掉,也就是定義一個物件必須要兩個引數的時候,檔案編譯不能通過。然後滿足這個條件後,系統就知道怎麼轉換了,不過這裡比較嚴格
以前我們構造物件的時候Fruit apple(“apple”)其實也已經有了一個轉換,從const char *的C字串格式,轉為string,在這裡,你再apple.isSame(“apple”)的話,蠢系統不懂得幫你轉換兩次,所以你必須要用 string()來先強制轉換,然後系統才知道幫你從string隱式轉換為Fruit,當然其實你自己也可以幫他完成。 cout<<”apple = /”apple/” ?:”<

int main()
{
       Fruit apple("apple", "green");
       Fruit orange("orange", "yellow");

       cout << "apple = orange? : " << apple.isSame(orange) << endl;
       //顯示轉換
       cout << "apple = /"apple/"? :" << apple.isSame(Fruit("apple", "green")) << endl;

       return 0;
}

在你不想隱式轉換,以防使用者誤操作怎麼辦?
C++提供了一種抑制建構函式隱式轉換的辦法,就是在建構函式前面加explicit關鍵字,你試試就知道,那時你再希望隱式轉換就會導致編譯失敗,但是,要說明的是,顯式轉換還是可以進行,出於不提供錯誤原始碼例子的原則,錯誤的情況就不提供了,自己試試吧