歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++隱式類類型轉換

C++可以定義如何將其他類型的對象隱式轉換為我們的類類型或將我們的類類型的對象隱式轉換為其他類型。為了定義到類類型的隱式轉換,需要定義合適的構造函數。

說明:可以用單個實參來調用的構造函數定義了從形參類型到該類類型的一個隱式轉換。

class Sales_item
{
public:
    Sales_item(const string &book = "") : isbn(book), units_sold(0), revenue(0.0) {}
    Sales_item(istream &is);
};

這兩個構造函數都定義了一個隱式轉換。因此,在期待一個Sales_item類型對象的地方可以使用一個string或一個istream對象。

string null_book = "9-999-99999-9";
item.Same_isbn(null_book);

這段代碼使用一個string類型對象作為實參傳遞給Sales_item的Same_isbn成員函數,該成員函數期待一個Sales_item對象作為實參。編譯器將使用接受一個string的構造函數從null_book生成一個新的Sales_item對象。新生成的(臨時的)Sales_item對象被傳遞給Same_isbn。

item.Same_isbn(cin);

這段代碼將cin對象隱式轉換為Sales_item對象,這個轉換執行接受一個istream的構造函數。這兩個Sales_item是臨時對象,一旦Same_isbn結束,就不能再訪問它。

下面看一個例子:

 1 #include <string>
 2 #include <iostream>
 3 using namespace std;
 4
 5 class Fruit                                //定義一個類,名字叫Fruit
 6 {
 7    string name;                        //定義一個name成員         
 8    string colour;                        //定義一個colour成員
 9
10 public:
11    bool isSame(const Fruit &otherFruit)  //期待的形參是另一個Fruit類對象,測試是否同名
12    {
13        return name == otherFruit.name;
14    }
15    void print()              //定義一個輸出名字的成員print()
16    {
17        cout<<colour<<" "<<name<<endl;
18    }
19    Fruit(const string &nst,const string &cst = "green"):name(nst),colour(cst){}  //構造函數
20
21    Fruit(){}
22 };
23
24 int main(void)
25 {
26    Fruit apple("apple");
27    Fruit orange("orange");
28    cout<<"apple = orange ?: "<<apple.isSame(orange)<<endl;  //沒有問題,肯定不同
29    cout<<"apple = apple ?:"<<apple.isSame(string("apple"))<<endl; //用一個string做形參?
30
31    return 0;
32 }

我們用string("apple")類型作為一個期待Fruit類型形參的函數的參數,結果是正確的。當把構造函數colour的默認實參去掉,也就是定義一個對象必須要兩個參數的時候,文件編譯不能通過。Fruit apple("apple")其實也已經有了一個轉換,從const char *的C字符串格式,轉為string。但apple.isSame("apple")這樣調用肯定是錯的,必須要用string()來先強制轉換,然後系統才知道幫你從string隱式轉換為Fruit。當然你也可以顯式幫它完成,apple.isSame(Fruit("apple"))。

可以通過將構造函數聲明為explicit,來防止在需要隱式轉換的上下文中使用構造函數。explicit關鍵字只能用於類內部的構造函數聲明上。在類的定義體外部所做的定義不再重復它。雖然不能隱式轉換了,但顯式轉換還是可以的,例如:apple.isSame(Fruit("apple"))。

說明:

(1)顯式使用構造函數只是終止了隱式地使用構造函數。任何構造函數都可以用來顯式地創建臨時對象。

(2)通常,除非有明顯的理由想要定義隱式轉換,否則,單形參構造函數應該為explicit。將構造函數設置為explicit可以避免錯誤,並且當轉換有用時,用戶可以顯式地構造對象。

(3)將構造函數設置為explicit的好處是可以避免因隱式類型轉換而帶來的語義錯誤,缺點是當用戶的確需要進行相應的類型轉換時,不能依靠隱式類型轉換,必須顯式地創建臨時對象。

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved