轉換函數筆記2----C++學習之路

  1.non-explicit-one-argument ctor

one-argument的意思就是,只要一個實參就夠了,但是你要給兩個也行。

代碼例子:

class Fraction 
{
public:
    Fraction(int num, int den=1)
        : m_numerator(num),m_denominator(den){}
    Fraction operator+(const Fraction& f){ return Fraction(....); }
private:
    int m_numerator;
    int m_denominator;
};
測試用例:

Fraction f(3,5);
Fraction d2 = f + 4;
當第二個語句使用f+4的時候,編譯器會自動去尋找是否有operator+這個函數,找到了我們發現,這條語句:
Fraction operator+(const Fraction& f){ return Fraction(....); }
+號左邊十個Fraction,右邊也是Fraction,設計成分數+分數。但是實際上卻是f+4,那麼編譯器就會去考慮4是否

能夠轉換成Fraction。編譯器發現這個語句:

Fraction(int num, int den=1)
        : m_numerator(num),m_denominator(den){}
那麼4就轉換成了4/1,那麼語句f+4就通過了編譯器。

整個過程就是先調用non-explicit ctor轉換爲Fraction,然後調用operator+。

  2.但是假如與之前的operator double()並存的話。

代碼:

class Fraction
{
public :
    Fraction (int num, int den=1)
        :m_numerator(num),m_denominator(den){}
    operator double() const{ return (double)( m_numerator/m_denominator);}
    Fraction operator+(const Fraction& f){ return Fraction(......); }

private:
    int m_numerator;
    int m_denominator;
};
測試用例:

Fraction f(3,5);
Fraction d2=f+4;  //[Error] ambiguous
這樣看起來,先將4轉換成4/1,與f相加得到一個Fraction,看似行得通。

但是看operator double(),將f轉換爲0.6,加上4得到4.6,那麼4.6是否能轉換爲Fraction?

這樣的話,編譯器就會引起歧義,就會報錯。

當然,這個代碼引起的問題和之前的轉換函數的筆記中的代碼是一樣的,但是在上一個筆記中使用者使用的是

double d=f+4;

所以得出結論,類內的設計以及是否會出現歧義,需要更多地去考慮使用者是如何使用的。

  3.explicit-one-argument ctor

這個的explicit的意思是明白的明確的,這告訴編譯器來,我這就是個明確的構造函數,你不能讓4編程4/1,只能用來當作構造函數。

代碼:

class Fraction
{
public :
    explict Fraction (int num, int den=1)
        :m_numerator(num),m_denominator(den){}
    operator double() const{ return (double)( m_numerator/m_denominator);}
    Fraction operator+(const Fraction& f){ return Fraction(......); }

private:
    int m_numerator;
    int m_denominator;
};
測試用例:

Fraction f(3,5);
Fraction d2=f+4;  //[Error]
這個時候這個加法就是失敗的,因爲找到operator+的時候,4無法轉換爲4/1,因爲explict,所以4無法轉換,所以報錯

這個explict百分90都用在構造函數,另外就使用在模板的一個很小的部分。

  4.回到轉換函數,標準庫中使用到的轉換函數。

代碼例子:

template <class Alloc>
class vector<bool,Alloc>
{
public:
    typedef __bit_reference reference;
pretected:
    reference operator[](size_type n) { return *(begin()+difference_type(n)); }
....
};
struct __bit_reference
{
    unsigned int* p;
    unsigned int mask;
    ...
public:
    operator bool() const { return !(!(*p & mask)) }
    ...
}
第一段代碼中,vector的語法是模板的偏特化,從裏面有個函數是對[]的重載。

它傳回的是reference,可以看得出,這個代碼傳回的是一個bool值,但是傳回的是reference。

這種設計方式稱爲代理。

那麼拿reference來代表一個bool值,就需要把reference轉換成一個bool,所以在__bit_reference中有一個轉換函數。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章