【问题标题】:C++: how to return object's set state when used as logical valueC ++:用作逻辑值时如何返回对象的设置状态
【发布时间】:2020-07-25 19:19:44
【问题描述】:

我有一些可以设置或不设置的类:

Class obj;

我希望它的值在逻辑中使用时返回是否已设置:

if ( obj )
    obj.Clear();

if ( !obj )
    obj.Set( "foo" );

我想添加一个到 bool 的隐式转换,但我想知道是否需要 int 或者是否有更好的方法来解决这个问题。

【问题讨论】:

  • 能否添加HasValue()之类的方法,或者重载!操作符?
  • if(obj) 将始终为真,除非 obj 为空。我建议添加一个方法并调用它来检查对象的状态。
  • @rhughes 我现在有 IsSet(),我想这就是你的想法。
  • std::optional<T> 可能就是您要找的。​​span>

标签: c++ oop c++11 operator-overloading


【解决方案1】:

可以定义bool操作符,如下

#include <iostream>

struct Object{
    bool state;
    explicit operator bool()const{
        return state;
    }
};
int main(){

    Object o1;
    Object o2;
    o1.state = false;
    o2.state = true;
    std::cout << "\no1 state is " << (o1?  "true": "false");
    std::cout << "\no2 state is " << (!o2?  "false": "true");
}

输出是

o1 state is false
o2 state is true

Live

【讨论】:

  • 您能否在您的友好答案中添加一点细节,解释编译器如何知道使用 bool() 运算符,以及为什么说 int() 不起作用或不会会更好吗?
  • 这是个好技巧!从未考虑过覆盖bool 运算符
  • operator bool 应该是explicit!否则你会得到奇怪的隐式转换,例如o1 + 42 将编译。
  • @HolyBlackCat 有趣;你有时间解释为什么吗?这可能是一个很好的答案,而不是评论。
  • @SwissFrank 仅此而已。使其成为explicit 意味着它只会由bool 演员或some sane circumstances 触发(例如用作if 中的条件,或循环,或? :,或作为操作数到! &amp;&amp; ||)。如果不是explicit,可以用蹩脚的方式触发,比如上面提到的o1 + 42
【解决方案2】:

您可以使用std::optionalstd::shared_ptr

示例 1:

std::optional<Object> obj = Object();

if (obj) obj->useIt();

obj.reset();

if (obj) ... ;

示例 2

std::shared_ptr<Object> obj = new Object();

if (obj) obj->useIt();

obj.reset();

if (obj) ... ;

【讨论】:

    【解决方案3】:

    您应该使用std::optional 表示可选值。这是自我记录,其他程序员知道他们在做什么,并且您避免检查自己类的不变状态(降低复杂性)。它还对值包装器使用 STL 约定(与迭代器、智能指针等相同)。

    如果您不想或根本无法使用它,请查看它的实现并遵循相同的规则:

    1. 实现布尔转换运算符(显式)
    2. 提供用于模板化方法的方法(如 std::optional::has_value()

    请注意,if (...) 对语句执行显式布尔转换。所以通常不需要隐式转换。为了避免使用重载时出现问题,您应该始终使用显式转换运算符。

    【讨论】:

    • 谢谢。该类已经具有设置或不设置的内部概念,因此不需要该模板。我不知道if 有一个明确的布尔转换。这或多或少地回答了我的问题。你的观点是什么 2.?如果你有时间,你能解释一下为什么这是个好主意吗?
    • 编写泛型函数时,通常不依赖参数运算符。例如,您不使用operator&amp;,而是使用std::addressof,因为您不知道类型以及运算符是否重载。因此,为一个类的所有运算符提供方法是很常见的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多