2014-06-05 46 views
2

我正在通過代碼...我找到了一個模板類,聲明如下。模板和運算符重載

template <class T> 
class tType 
{ 
public: 
    T value; 
    T operator=(T val){ value = val; return value; } 
    tType<T> operator=(tType<T> &val){ value = val.value; return *this; } 
    operator T(){ return value; } 
}; 

我還發現運營商超載像下面...

****** 1 ******

template <class T> 
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); } 

我不明白,當上面的操作符被稱爲... cos當我做...

int main(void) 
{ 
    tType<int> x; 
    x = 5; 
    if (5 == x) 
    { 
     cout << "Both are equal" << endl; 
    } 
    return 0; 
} 

上述操作符不是getti NG叫......和還在工作......我也寫了下面的測試,下面的代碼片段獲取調用代碼...

template<class T> 
bool operator==(int x, tType<T>& val) { return (x == val.value); } 

我不知道該給誰打電話*** ** 1 *****

回答

2

結合非const引用的論據的==運營商嘗試 - 值分別爲「5」是不適合於...的參數應該是const

template <class T> 
bool operator==(const T& val, const tType<T>& tval) { return val == tval.value; } 

由於無線我仍然只支持例如5 == my_tType而不是my_tType == 5,你可能還希望提供...

template <class T> 
bool operator==(const tType<T>& tval, const T& val) { return val == tval.value; } 

...和... my_tType1 == my_tType2

template <class T> 
bool operator==(const tType<T>& tval1, const tType<T>& tval2) { 
    return tval1.value == tval2.value; } 

這使您可以比較的最大控制。另一種方法是允許從T的角度隱含構建tType,但隱式構造和轉換操作符現在普遍不受歡迎 - 它們可能會導致含糊不清和臨時創建的臨時對象難以調試。另一個問題的主題....

當你說「上述操作員沒有被調用...並仍在工作」 - 實際發生的是tType::operator T()(它返回value;)被隱式調用,返回可以比較的int - 作爲int - 至5。因此 - 你有一個比較,但不使用自定義operator==。這是找到函數調用的「最佳匹配」的正常結果。

1

改變功能

template <class T> 
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); } 

template <class T> 
bool operator==(T const& val, tType<T> const& tval) { return(val == tval.value); } 

template <class T> 
bool operator==(T val, tType<T> tval) { return(val == tval.value); } 

您的功能沒有得到所謂的,因爲5不能轉換到int&

3

這是正確的,您的operator==未被調用的原因是因爲缺少const標識符。在這種情況下,文字5無法作爲變量參考傳遞給參數T& val。但是,這不是完整的故事。

正如您所指出的那樣,即使函數未被調用,代碼仍然會編譯並運行。

您的代碼仍然工作的原因是由於conversion operatoroperator T(){ return value; }

轉換運算符允許從一種類型到另一種類型的隱式轉換。例如:

struct Number { 
    Number(int x) : value(x) { } 
    operator int() { return value; } 
private: 
    int value; 
}; 

int main() { 

    Number n(5); 
    int x = n;   // 5 -- operator int() at work 
    int y = n + x;  // 10 -- operator int() at work 
    Number z = x + y; // 15 -- Number(int) at work 

    cout << x <<" "<< y <<" "<< z << endl; 
    return 0; 
} 

這裏,operator int()允許n到轉換成int用於分配給x和要轉換爲int用於添加與x(所得int然後分配給y),而一元構造Number(int)允許x + y的結果轉換回Number

在代碼中,5 == x仍然編譯因爲tType<int>x經由其operator int()成員函數轉換爲int,然後將該所得的int抵靠字面5比較。


但是,這可能不是一個非常好的類設計。例如,爲了比較兩個tType<T> s,其中一個需要投入T

template <class T> 
bool operator==(const T& val, const tType<T>& tval) { 
    cout << "operator==(const T& val, const tType<T>& tval) was called." << endl; 
    return(val == tval.value); 
} 

//... 

cout << (tType<int>() == tType<int>()) << endl; // calls operator==(const T&, const tType<T>&) 

你寧願有兩個tType<T>秒的operator==

另一個甚至更​​大的問題是,這是不是對稱的:

cout << (x1 == 5) << endl;  // calls operator==(int,int) (the built-in function) 

哎呀!


要解決所有這些問題,有一個非常簡單的設計解決方案。這是從斯科特邁耶斯的書Effective C++ Third Edition(一本驚人的書)。

不是轉換回T與轉換運算符,類應該包括一個隱含的一元構造函數T的轉換高達tType<T> s,而應該準確地申報一個operator==tType<T> S:

template <class T> 
class tType 
{ 
public: 
    tType<T>(const T &val) : value(val) { }  // unary non-explicit constructor 
    tType<T> operator=(const tType<T> &val){ value = val.value; return *this; } // only need one 

    T val() { return value; } 
private: 
    T value;   // Note also value is private (encapsulation) 
}; 

template<class T> 
bool operator==(const tType<T>& a, const tType<T>& b) { return (a.val() == b.val()); } 

重要更改:

  1. 添加了一個構造函數,它具有單個值;這允許將Ts轉換成tTypes。
  2. 刪除賦值運算符采取T S(因爲現在我們可以將它們轉換爲tType秒。
  3. 只能有一個平等的運營商,它有兩個const tType<T>& S,這意味着operator==可以處理的T S和tType<T>小號的任意組合(或,甚至更好,任何可轉換成任何一種的東西)