3

考虑以下代码:

class Truth
{
public:
    Truth(bool val) : value(val) {}
    bool operator!() {std::cout<<"operator!()"<<std::endl; return !value;}
    operator bool() {std::cout<<"operator bool()"<<std::endl; return value;}
private:
    bool value;
};

int main()
{
    Truth t(true);

    if(!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(!!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    return 0;
}

在语句中if(!t)if(!!t)重载的operator!()实现被调用,而(并不奇怪)在语句if(t)中,重载的operator bool()实现被调用。

但是,如果operator!()实现被注释掉,在所有 3 个语句中,operator bool()都会被调用。

我理解“为什么”会发生这种情况,但我担心的是,重载逻辑 NOT 运算符(!)似乎错过了一半的真值评估语义,而bool类型转换运算符似乎很好地覆盖了它们。

我是否遗漏了什么,或者是否应该不鼓励逻辑 NOT 运算符的重载以支持 bool 类型转换?

4

1 回答 1

5

在 C++11 中,您可以简单地重载explicit operator bool(). operator!除非你想让它做一些不同的事情,否则没有理由超载——如果你认为你想要那样,你可能应该再想一想。

从历史上看,重载operator bool会为隐式转换为任何数字类型打开大门,这可能会导致混淆、歧义和细微的错误;所以最好不要那样做。重载operator!是一种允许在条件句中使用的简单方法,而无需打开那扇门,如果您不想陷入安全 bool idiom的困境。(该链接仅出于历史兴趣;由于显式转换运算符,该成语在 C++11 中已过时。)

于 2014-02-25T02:05:08.573 回答