C++ 如何从类对象返回值?

C++ 如何从类对象返回值?,c++,class,operator-overloading,C++,Class,Operator Overloading,是否可以让类对象返回真/假值,以便我可以执行以下操作: MyClass a; ... if (a) do_something(); class Testable { typedef void (Testable::*bool_type)() const; void this_type_does_not_support_comparisons() const {} public: operator bool_type() const { ret

是否可以让类对象返回真/假值,以便我可以执行以下操作:

MyClass a;
...
if (a)
    do_something();
  class Testable {
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    operator bool_type() const {
      return /* condition here */ ? 
        &Testable::this_type_does_not_support_comparisons  // true value
        : 0; // false value
    }
  };
我可以(几乎)完成我想通过超载的!接线员:

class MyClass {
    ...
    bool operator!() const { return !some_condition; };
    ...
}

main()
    MyClass a;
    ...
    if (!a)
        do_something_different();
operator void * () const { return some_condition; };
operator bool() { /* ... */ }

但是我还没有找到一种方法来重载“空”操作符。当然,使用==操作符检查true/false也是可能的,事实上,到目前为止我一直在这么做。

重载void*cast操作符:

class MyClass {
    ...
    bool operator!() const { return !some_condition; };
    ...
}

main()
    MyClass a;
    ...
    if (!a)
        do_something_different();
operator void * () const { return some_condition; };
operator bool() { /* ... */ }
这就是流的工作方式,允许您说:

if ( cin ) {
   // stream is OK
}
使用void*而不是bool可以防止在某些上下文中错误地使用强制类型转换,例如算术,在这些上下文中它是不可取的。当然,除非您想在这些上下文中使用它。

尝试重载(bool)运算符:

class MyClass {
    ...
    bool operator!() const { return !some_condition; };
    ...
}

main()
    MyClass a;
    ...
    if (!a)
        do_something_different();
operator void * () const { return some_condition; };
operator bool() { /* ... */ }

显而易见的解决方案——通过
操作符bool
提供到
bool
的隐式转换——是个坏主意

这就是标准库使用
操作符void*
的原因,如Neil的回答所示

然而,值得指出的是,即使这种解决方案也有缺陷,因此不再被认为是安全的。不幸的是,想出一个更好的解决方案并不是件小事


在Artima有一篇文章描述了。对于一个真正的库来说,这绝对是一个好办法,因为它提供了最健壮的接口,最难被错误使用。

奇怪的是,到目前为止还没有人提到。到目前为止所描述的所有其他解决方案都有缺点(您可能关心,也可能不关心),所有这些方法都在本文中描述。简而言之,safe bool成语是这样的:

MyClass a;
...
if (a)
    do_something();
  class Testable {
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    operator bool_type() const {
      return /* condition here */ ? 
        &Testable::this_type_does_not_support_comparisons  // true value
        : 0; // false value
    }
  };

bool
运算符比
void*
运算符更具体。你能给我举一个错误的例子吗?谢谢。这很好,只是我必须在(void*)中加入一些条件。但是,这里的其他人都建议重载bool(),这也可以很好地工作,使代码看起来更容易理解:)您能举个例子说明该解决方案可能出现的问题吗,所以我可以更好地理解你的建议的好处?@Dacav我不知道你们更具体地说是什么-一个void*不能是算术表达式的一部分,所以这个类不能以
a+1
的形式使用,正如我所建议的,这可能是OP想要的,也可能不是OP想要的。@Terje见上面的评论。我已经稍微修改了我的答案。@Neil Butterworth:谢谢,现在我看到问题了。我尝试了一些类似于
static\u cast(3+m)
的东西,其中m是一个类重载bool的实例,编译器实际上接受了它!这主意不好,我很沮丧。详细信息请参见Neil的答案。-1这会产生意想不到的副作用,另一种解决方案请参见Safe Bool成语。文章中描述的“问题”中,至少有一个是有点可疑的,即删除void*cast的结果。我使用的所有编译器在这方面都给出了至少一个警告,因为它是UB。是的,我删除了我的建议,因为它有误导性的缺陷。如果你真的想让它在任何情况下都像布尔一样被对待,那么选择布尔就是完美的。铸造空心*有其价值,但也有其缺陷。这是一个通用的解决方案,如果在所有上下文中都应该将其视为bool,那么强制转换为bool就是一个可行的方法。好了,在C++0x中,您将能够显式标记转换运算符,从而消除对安全bool习惯用法的需要?这也是最复杂的方法。也许值得一提的是,“我是否需要能够在需要bool的地方直接使用该类?”只需提供一个
is_ok
成员函数,或者重载
operator()
返回bool,然后测试
if(a())
。谢谢你的链接,Konrad(和sbk)。这是一本非常有趣的书,当然还有一些东西可以留作将来参考。@jalf:没错,这就是为什么我加上了“真正的图书馆…”。关键是,对于库来说,用户的利益总是大于实现者的努力。一个简单易用的界面赢得了胜利。