为什么转换为引用会干扰转换为布尔

Why does conversion to reference interfere with conversion to bool?

本文关键字:转换 布尔 干扰 引用 为什么      更新时间:2023-10-16

似乎如果我有一个到引用的转换运算符,那么这个运算符将优先于到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 << "d1an";
    if (D1 d1b = D1('b', 'a')) std::cout << "d1bn";
    if (D2 d2a = D2('a', 'a')) std::cout << "d2an";
    if (D2 d2b = D2('b', 'a')) std::cout << "d2bn";
    return 0;
}

该程序的输出为:

d1a
d2a
d2b

请注意,d1b不在输出中,这意味着对bool的转换与我对D1的预期一样。但是,对于D2,向引用类型的转换似乎优先于bool的转换。为什么会发生这种情况?我是否可以对D2进行简单的更改,以允许bool转换在if检查中优先?

目前,我正在使用D1,并为其添加一个赋值运算符,以实现引用的行为。

实际上,它与int&无关,而是const的问题:

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

d2aD2,而不是const 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 << "d1an";
if (const D1 d1b = D1('b', 'a')) std::cout << "d1bn";
if (const D2 d2a = D2('a', 'a')) std::cout << "d2an";
if (const D2 d2b = D2('b', 'a')) std::cout << "d2bn";

D1 d1a = D1('a', 'a');
D1 d1b = D1('b', 'a');
D2 d2a = D2('a', 'a');
D2 d2b = D2('b', 'a');
if (d1a) std::cout << "d1an";
if (d1b) std::cout << "d1bn";
if (d2a) std::cout << "d2an";
if (d2b) std::cout << "d2bn";

打印

d1ad2a

你有

if (D2 d2a = D2('a', 'a')) std::cout << "d2an";
if (D2 d2a = D2('b', 'a')) std::cout << "d2bn";

如果在两种情况下都不使用相同的名称,会发生什么?如果我用替换第4个if,则输出中只有d1ad2a

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