2014-10-07 29 views
4

我有下面的代碼構造代替或類型轉換操作

class A { 
    private: 
      int n; 

    public: 
      A(int n) : n{n} {} 
      A(const A & a) : n{a.n} {} 
    }; 

    class B { 
    private: 
      int m; 
    public: 
      B(int n) : m{n} {} 
      operator A() const { return A(m); } 
      operator int() const { return m; } 

    }; 

    int main(int, char**) 
    { 
      B b{1}; 

      (A)b;    // Fails 
      static_cast<A>(b); // Fails 
      b.operator A();  // OK 
    } 

這種失敗

call of overloaded ‘A(B&)’ is ambiguous 

(GCC,但VC++和鐺似乎處理同樣的方式)

我以爲所有三個都是完全一樣的東西。使用B的運算符A()進行轉換。顯然這不是發生了什麼事情。爲什麼?

這個問題很容易通過使int()運算符顯式解決,但我在解釋之後不是解決方案。

+0

這就是爲什麼我們現在有顯式類型轉換操作符現在,如'顯式運算符A()const;'。所以static_cast和C風格的轉換是可能的,但不是隱式轉換。 – 2014-10-07 16:58:29

回答

4

A可以從intconst A&構成,B可以轉換爲這兩種,因此這些表達是ambigious,因爲編譯器不能知道兩個不同路徑是否從B導致相同的結果產生一些A

這是由於static_cast小號確定可能的轉換路徑的方式:

如果new_type類型的臨時對象可以聲明,並用表達初始化,如通過new_type Temp(expression);,這可能涉及隱式轉換,呼叫到new_type的構造函數或調用用戶定義的轉換運算符,然後static_cast<type>(expression)計算並返回該臨時對象的值。 (ref

注意這一部分:

這可能涉及隱式轉換,向new_type構造一個呼叫或一個用戶定義的轉換運算符的呼叫

你可以隱含地將B轉換成int,然後從int構造A

或者您可以根據轉換運算符將B轉換爲A

這就是在這裏使用C風格或static_cast時出現歧義的地方。

我會建議使構造函數(A(int)explicit,而不是操作員。這通常是想要的行爲。這會導致static_cast<A>(b)不可信的行爲:使用operator A()

注意A a = b;是明確的:它會使用operator A(),因爲隱式轉換喜歡的用戶定義的轉換(ref

+3

我認爲關鍵是'(A)b'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''我認爲關鍵點是'前者意味着編譯器查看'A'的構造函數,並查看是否可以使用'b'來調用其中的任何一個(並且通過兩條不同的路徑發現它可以是)。後者會查看'B'的轉換運算符,並按照OP的預期行事,但這不是語言的工作原理。 – 2014-10-07 16:10:23

+0

似乎我不明白演員和轉換之間的區別。我雖然認爲演員會強制轉換。 – EVK 2014-10-07 16:10:23

+0

不一定如此。 C風格的轉換本身非常模糊(它們根據類型和上下文對不同的C++轉換進行評估)。經驗法則:99%的時間static_cast <>是正確的。然後:類型轉換由演員執行。也許這會爲你解決問題...... – dom0 2014-10-07 16:12:05

相關問題