2013-07-11 80 views
10

看來如果我有一個轉換操作符到引用,該操作符將優先於轉換爲bool。爲什麼會發生這種情況,我該如何解決?爲什麼轉換爲參考會干擾轉換爲bool?

(如果它的事項,我使用GCC 4.5我在ideone驗證了同樣的行爲被發現與GCC-4.7.2。)

假設如下:

class B { 
protected: 
    const int a_; 
    int b_; 
    B (int b, int a) : a_(a), b_(b) {} 
public: 
    operator bool() const { return b_ == a_; } 
}; 

class D1 : public B { 
public: 
    D1 (int b = 0, int a = 0) : B(b, a) {} 
    operator int() const { return b_; } 
}; 

class D2 : public B { 
public: 
    D2 (int b = 0, int a = 0) : B(b, a) {} 
    operator int &() { return b_; } 
}; 

然後,假定它們是在一個簡單的程序中使用這樣的:

int main() { 
    if (D1 d1a = D1('a', 'a')) std::cout << "d1a\n"; 
    if (D1 d1b = D1('b', 'a')) std::cout << "d1b\n"; 
    if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
    if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
    return 0; 
} 

該程序的輸出是:

d1a 
d2a 
d2b 

請注意,d1b不在輸出中,這意味着轉換爲bool的工作方式與我預期的相同,爲D1。但是,對於D2,似乎轉換爲參考類型優先於bool轉換。爲什麼發生這種情況?是否可以對D2進行簡單的更改以允許bool轉換優先於if檢查?

目前,我使用D1並添加了賦值運算符來實現引用的行爲。

+0

嗯,是的,我同意我可能應該能夠自己發現這一點,但是除了懲罰我對我來說糟糕的一天之外,是否還有更多的投票原因呢? – jxh

回答

9

其實,它無關int&,這是const -ness的問題:

operator bool() const { return b_ == a_; } 
       /* ^^^^^ */ 
       /* vvvvv */ 
operator int &() { return b_; } 

d2a是一個D2,而不是一個​​,所以非常量轉換運算符更合適。如果你把它寫成

operator const int &() const { return b_; } 

你會得到預期的行爲,請參閱http://ideone.com/vPPPYV

請注意,如果您使用const版本的對象operator const int&不會干涉甚至,以下行仍然會導致您預期的行爲(見http://ideone.com/DTE0xH):

if (const D1 d1a = D1('a', 'a')) std::cout << "d1a\n"; 
if (const D1 d1b = D1('b', 'a')) std::cout << "d1b\n"; 
if (const D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
if (const D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
+1

謝謝,這說明對我來說完全匹配的轉換序列。解決的辦法是添加''bool'轉換運算符的非'const'版本。 – jxh

+1

夢幻般的答案! – Antonio

1

D1 d1a = D1('a', 'a'); 
D1 d1b = D1('b', 'a'); 
D2 d2a = D2('a', 'a'); 
D2 d2b = D2('b', 'a'); 
if (d1a) std::cout << "d1a\n"; 
if (d1b) std::cout << "d1b\n"; 
if (d2a) std::cout << "d2a\n"; 
if (d2b) std::cout << "d2b\n"; 

打印

d1a 
d2a

我。

你有

if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
if (D2 d2a = D2('b', 'a')) std::cout << "d2b\n"; 

如果你沒有在這兩種情況下使用相同的名稱,會發生什麼? 這裏只有d1a和輸出d2a如果我更換第四屆如果

if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
+0

結果是相同的(見http://ideone.com/CpPXZS)。我會更新這個問題。 – jxh

+0

好吧,好吧... MSVC++ 11(VS12)不會打印'd2b'。 – Pixelchemist

+0

+1,我發現GCC-C++和MSVC++之間的行爲有所不同。 – jxh