1. 程式人生 > >c++ 隱式轉換帶來的問題

c++ 隱式轉換帶來的問題

            編譯器經常會揹著我們做一些我們不希望發生的事情,最典型的是隱式轉換。不過慶幸的是,編譯器只會幫助我們進行一次轉換,而不會無休止的隱式轉換,直至滿足條件為止。例如,下面先定義一個Array模板類:

template<class T>class Array {
    public:
    Array(int lowBound,int highBound);
    Array(int size);
    T& operator[](int index);
    bool  operator==(const Array<int>& lhs,const Array<int>& rhs);
};

而在使用中,

Array<int> a[10];
Array<init>b[10];
for(int i=0;i<10;i++) {
     if(a==b[i]) {
            //發生點什麼
      }
}

由於書寫錯誤,本來是a[i]==b[i],而出現了上面的a==b[i]。但是編譯器並不會報錯,由於在Array模板類中有過載了==操作符,而且引數都為Array陣列。在Array的建構函式中存在只有一個int型別的建構函式,因此編譯器會根據b[i],幫我們產生一個臨時Array物件,然後呼叫==操作賦函式。 編譯器沒有報錯,而出現這種情況,可以將建構函式新增一個宣告:explicit。這樣子編譯器便不能因隱式型別轉換的需要而呼叫它們。編譯器呼叫建構函式幫我們產生需要的物件,但是它只會產生一次,而不會在臨時物件的基礎在呼叫建構函式產生需要的物件。例如:

template<class T>class Array {
    public:
    class ArraySize {
       public:
           ArraySize(int numElements):theSize(numElements) {}
           int size() const {return theSize;}
       private:
           int theSize; 
    };
    Array(int lowBound,int highBound);
    Array(ArraySize size);
    T& operator[](int index);
    bool  operator==(const Array<int>& lhs,const Array<int>& rhs);
};

同樣在使用中出現前面的錯誤,即

Array<int> a[10];Array<init>b[10];
for(int i=0;i<10;i++) {
     if(a==b[i]) {//原意是a[i],現在出現了錯誤
            //發生點什麼
      }
}

編譯器需要一個Array<int>的物件在==的右手邊,得以針對Array<int>物件呼叫operator==,但是此刻並沒有“但一自變數,型別為int”的建構函式。同時,編譯器不會考慮將int轉換為一個臨時性的ArraySize物件(這是可行的),然後在根據這個臨時物件產生必要的Array<int>物件。即編譯器需要需要做兩件事情:1.將int轉換為ArraySize型別臨時物件;2.再將ArraySize臨時物件轉換為Array<int>物件。然後編譯器不會這麼做,而會對上面的程式碼發錯錯誤訊息。幸好編譯器不會做這種事情,否則我們的程式不知道會出現多少潛在的錯誤。不管怎麼樣,隱式轉換總是會帶來隱患。需要小心謹慎!