2012-09-09 82 views
6

讓我們有這樣的代碼:C++:轉換運算符與賦值運算符與轉換構造優先

Test1 t1; 
Test2 t2; 
t1 = t2; 

我相信有三種方式可以實現t1 = t2

  • (或更多?)在Test1
  • 超載賦值運算符重載型投運營商Test2
  • 創建Test1(const Test2&)轉換構造

根據我的GCC的測試,這是使用何種優先級:

  1. 賦值運算符
  2. 轉換構造函數和類型轉換操作符(曖昧)
  3. 常量轉換構造和const類型轉換運算符(含糊)

請幫我理解爲什麼這個優先級。

我用於測試代碼(取消註釋一些線路試行)

struct Test2; 
struct Test1 { 
    Test1() { } 
    Test1(const Test2& t) { puts("const constructor wins"); } 
// Test1(Test2& t) { puts("constructor wins"); } 
// Test1& operator=(Test2& t) { puts("assign wins"); } 
}; 

struct Test2 { 
    Test2() { } 
// operator Test1() const { puts("const cast wins"); return Test1(); } 
// operator Test1() { puts("cast wins"); return Test1(); } 
}; 


int main() { 
    Test1 t1; 
    Test2 t2; 
    t1 = t2; 
    return 0; 
} 
+0

'Test1 :: Test1(const Test2&)'不是「複製構造函數」,它是一個「轉換構造函數」。 – aschepler

+0

這篇文章解釋了爲什麼轉換運算符具有更高的優先級:http://stackoverflow.com/questions/1384007/conversion-constructor-vs-conversion-operator-precedence –

回答

13

聲明t1 = t2;等同於:

t1.operator=(t2); 

現在重載決議的一般規則。如果有直接匹配,那就是所選的一個。如果不是,則隱式轉換被認爲與(自動生成的,「隱式定義的」)複製賦值運算符一起使用。

有兩種可能的隱式用戶定義轉換。所有用戶定義的轉換計數相等,並且如果兩者都定義,過載是不明確的:

  • 經由Test1::Test1(Test2 const &)轉換構造轉換t2Test1

  • 通過Test2::operator Test1() const轉換操作符將t2轉換爲Test1

+0

在@ Luchian的第二個ideone示例中,轉換函數獲勝是因爲它綁定'Test2&'到't2',而不是'const Test2&'。我認爲http://ideone.com/U38vK也應該是模棱兩可的,但似乎g ++更喜歡構造函數。 – aschepler

+2

啊哈。 g ++如果你問'âpedantic',會叫他們模糊不清。頑皮的默認g ++。 – aschepler

+0

@KerrekSB:如果轉換操作符不是常量,它會跳過轉換構造函數,並且沒有歧義。 http://liveworkspace.org/code/7795254ae49b4d6350f0ede57615e4c6 –