【问题标题】:How can I return a value from a class object?如何从类对象返回值?
【发布时间】:2011-03-26 22:37:12
【问题描述】:

是否可以让类对象返回真/假值,所以我可以这样做:

MyClass a;
...
if (a)
    do_something();

我可以通过重载 !运营商:

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

main()
    MyClass a;
    ...
    if (!a)
        do_something_different();

但我还没有找到一种方法来重载“空”运算符。当然,使用 == 运算符来检查真假也是可以的,这也是我目前一直在做的事情。

【问题讨论】:

    标签: c++ class operator-overloading


    【解决方案1】:

    重载 void * cast 操作符:

    operator void * () const { return some_condition; };
    

    这就是流的工作方式,让你说:

    if ( cin ) {
       // stream is OK
    }
    

    使用 void * 而不是 bool 可以防止在某些情况下错误地使用强制转换,例如算术,在这种情况下,它是不可取的。当然,除非您想在这些情况下使用它。

    【讨论】:

    • bool 运算符比 void * 更具体。您能否举一个涉及强制转换为 bool 的错误示例?
    • 谢谢。这工作得很好,除了我必须将 some_condition 转换为 (void*)。但是,这里的其他人都建议重载 bool(),它也可以正常工作,并使代码看起来更容易理解:) 你能否举例说明该解决方案可能出现的问题,以便我更好地理解你的建议?
    • @Dacav 我不知道你们更具体的意思 - void * 不能成为算术表达式的一部分,因此该类不能以 a + 1 的形式使用,正如我所建议的那样或者可能不是 OP 想要的。
    • @Terje 见上面的评论。我已经稍微编辑了我的答案。
    • @Neil Butterworth:谢谢,现在我看到了问题所在。我试图找出像static_cast<int>(3 + m) 这样的东西,其中 m 是类重载 bool 的实例,编译器实际上接受了它!
    【解决方案2】:

    尝试重载 (bool) 运算符:

    operator bool() { /* ... */ }
    

    【讨论】:

    • 坏主意,气馁。有关详细信息,请参阅 Neil 的答案。
    • -1 这有意想不到的副作用,请参阅 Safe Bool Idiom 以获得替代解决方案。
    【解决方案3】:

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

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

    但是,值得指出的是,即使是这种解决方案也存在缺陷,因此不再被认为是安全的。不幸的是,想出更好的解决方案并非易事……

    Artima 上有一篇文章描述了safe bool idiom。对于一个真正的库,这绝对是要走的路,因为它提供了最健壮的接口,最难用错。

    【讨论】:

    • 也是最复杂的方法。可能值得问“我是否需要能够直接在需要布尔值的地方使用该类?”只提供一个is_ok 成员函数可能更简单、更明智,或者可能重载operator() 以返回一个布尔值,然后测试if (a())
    • 感谢您的链接,康拉德(和 sbk)。这是非常有趣的阅读,当然可以保留以供将来参考。
    • @jalf:是的,这就是为什么我添加了“对于真正的库......”。关键是,对于一个库来说,对用户的好处总是超过了实现者的努力。易于使用且易于使用的界面胜出,毫无疑问。
    【解决方案4】:

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

      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
        }
      };
    

    【讨论】:

    • 文章中描述的至少一个“问题”,删除了一个void * cast的结果,有点可疑。我使用的所有编译器都至少对此给出警告,因为它是 UB。
    • 是的,我正在删除我关于转换为 bool 的建议,因为它存在误导性缺陷。如果您真的希望它在所有情况下都被视为 bool,那么转换为 bool 是完美的。转换为 void* 有其价值,但也有其缺陷。这是要采用的一般解决方案,如果 真的 在所有情况下都应被视为 bool,则强制转换为 bool 是要采用的解决方案。
    • AFAIK,在 C++0x 中,您将能够标记转换运算符显式,从而不再需要安全的布尔成语?
    猜你喜欢
    • 2020-02-27
    • 1970-01-01
    • 2016-02-16
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 2017-08-10
    • 2011-07-27
    相关资源
    最近更新 更多