2013-07-11 85 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