2013-01-03 85 views
1

下面是一個重載賦值運算符的模板類的示例。鑑於此類:在模板類上覆蓋賦值運算符時出現奇怪的行爲

template<class Type> 
class Attribute 
{ 
public: 

    Type operator=(const Type rhs) 
    { 
     mData = rhs; 
     return mData; 
    } 

private: 

    Type mData; 
}; 

爲什麼下面的代碼沒有任何錯誤地編譯?

Attribute<std::string> str; 
str = 0; 

雖然看似矛盾,這樣的代碼:

std::string test; 
test = 0; 

產生以下錯誤?

error C2593: 'operator =' is ambiguous 
+0

首先,總是使用const引用重載賦值運算符,所以這應該是'Type operator =(const Type&rhs)' – legends2k

+0

@ legends2k不是真的。通過價值允許您使用複製和交換成語來強有力的例外保證。此外,它爲編譯器提供了更多機會來消除不必要的副本,並在可用時自動調用移動構造函數(僅限C++ 11)。 – Tomek

回答

2

std::string已經超負荷operator=,你的代碼編譯罰款,但執行字符串構造的時候,因爲它不接受NULL(感謝Potatoswatter)

basic_string& operator=(const CharT* s); 

注有不確定的行爲:str = 0;等於

std::string str = std::string(NULL); 

std::string test; 
test = 0; 

在這裏,編譯器不能扣除0是字符類型或指針,所以它是ambig uous具有小於兩個運算符重載:

basic_string& operator=(const CharT* s); 
basic_string& operator=(CharT ch); 

手動施放0爲char或char*應該使你的代碼編譯,但你應該避免這樣做。

+0

那爲什麼這個代碼不能編譯? std :: string test; \t test = 0; – jlanisdev

+0

@jlanisdev不同之處在於'std :: string test;測試= 0;'調用賦值運算符不復制構造函數。 – billz

+0

@jlanisdev因爲它滿足兩個不同的賦值運算符重載。你可以從一個字符's ='x';'進行賦值,但是你不能從一個字符構造'std :: string s('x');'編譯器報告一個模糊的過載。 – Potatoswatter

1

std::string具有two assignment operators

basic_string& operator=(const CharT* s); 
basic_string& operator=(CharT ch) 

和0可以匹配前者和後者。怎麼樣? 0是一個有效的字符,the null char,它也可以表示指針的NULL值。因此編譯器會拋出error C2593: 'operator =' is ambiguous

至於爲什麼是接受它在你的Attribute類時,編譯器能夠建立基於this constructor

basic_string(const CharT* s, const Allocator& alloc = Allocator());

爲std :: string並將它作爲你的函數Type operator=(const Type rhs)rhs;此行爲是因爲編譯器implicit conversion