條款24:若所有參數皆需類型轉換,請爲此採用non-member函數

條款24:若所有參數皆需類型轉換,請爲此採用non-member函數
(Declare non-member functions when type conversions should apply to all parameters.)

內容:
    平時在我們的coding過程當中,我們有時候會碰到這樣一些情況:我傳進去的實參與聲明函數的形參並不是同
一類型的,函數調用竟然能夠成功!這個聽起來很不可思議是不是,那麼我這裏給你說一個編譯器的"祕密",也許你在
聽完以後,你或許有可能對你說的那些"不可思議的事情"就不以爲然了.
    我在這裏要說的"祕密"就是:當函數的實參類型與形參的出現不一致時候,編譯器會盡它最大的能力去尋找合理
類型轉換方案進行隱式轉換,使它們之間的類型達到一致,從而完成函數的調用過程,當然如果最後還是沒有找到合
適的類型轉換策略,編譯器就會給出"類型不匹配"的編譯錯誤.不怎麼理解?好,下面我來舉個例子來說明這個問題.
    假設現在有一個內置類型int的代理類IntDelegate,當然它就有很多特性,而這裏我們要說的是它的乘法操作,
你自然就寫出瞭如下的代碼:
    class IntDelegate{
    public:
        IntDelegate(int value = 0):intValue_(value){}
        IntDelegate(const IntDelegate& rhs){
            intValue_ = rhs.intValue_;
        }
        const IntDelegate operator*(const IntDelegate& rhs){
            IntDelegate result;
            result.intValue_ = intValue_ * rhs.intValue_;
            return result;
        }
        int getValue()const{
            return intValue_;
        }
        ...
    private:
        int intValue_;
        ...
    };
    wow,寫的不錯,下面我們來看看有沒有什麼問題,怎麼去看?暈,"實踐是檢驗真理的唯一標準",寫代碼測試一下:
    //test.cpp
    ...
    IntDelegate a(1),b(2);
    IntDelegate c = a*b; //ok.
    c = a * 2;           //Line1: ok.
    c = 2 * a;           //Line2: error,喔歐,乘法交換律失敗羅!shit!
    我們先來看Line1,你這裏奇怪了?咦?這裏的2壓根就不是IntDelegate類型,怎麼也能編譯的過?請注意
IntDelegate的構造函數是一個非explicit構造函數,這也就意味着編譯器可以對它進行隱式轉換,這種轉換等價
代碼如下:
    IntDelegate tempt(2);
    c = a * tempt;
    Line1現在該理解了吧?呵呵,我們接着來看Line2,這裏的2爲什麼不能擁有上面的隱式轉換呢?原因很簡單:只有
位於參數列表內的參數纔是隱式轉換的合格參與者.顯然這裏的a纔是那位合格者,嗚嗚....,不公平,我需要兩個都能
夠進行轉換.喔,問題不大!你想想,既然只有作爲參數列表才能進行隱式轉換,我們這裏就很自然地想到把2也作爲參
數列表中的一員,這樣不就搞定了嘛,呵呵!我們來修改一下代碼,這裏我們就需要變換一下操作符*的實現函數的函數
原型:
    const IntDelegate operator*(const IntDelegate& lhs,const IntDelegate& rhs){
        return IntDelegate(lhs.getValue()*rhs.getValue());
    }
    在運行一下上面的測試代碼,全部通過,結果完全真確,恭喜你!

    請記住:
    ■ 如果你需要爲某個函數的所有參數(包括被this指針所指的那個隱喻參數)進行類型轉換,那麼這個函數必須是個non-member.

發佈了62 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章