C++ C++;默认枚举值用法

C++ C++;默认枚举值用法,c++,enums,default-value,C++,Enums,Default Value,此讨论是关于默认值的名称: 然而,最近与我交谈的许多人认为默认枚举值有害、不必要,并且可能导致不良做法 作为一个例子,考虑如下: enum eJobStates { JOB_STATE_INITIALISING, JOB_STATE_PROCESSING, JOB_STATE_DONE }; 作业处于(比如)作业状态(未知)是没有意义的,但是您可以想象,任何可能用于监控所述作业的结构都可以使用这样的值 在定义枚举时,是否有关于创建默认值的最佳实践/经验法则?是否应尽可

此讨论是关于默认值的名称:

然而,最近与我交谈的许多人认为默认枚举值有害、不必要,并且可能导致不良做法

作为一个例子,考虑如下:

enum eJobStates
{
    JOB_STATE_INITIALISING,
    JOB_STATE_PROCESSING,
    JOB_STATE_DONE
};
作业处于(比如)作业状态(未知)是没有意义的,但是您可以想象,任何可能用于监控所述作业的结构都可以使用这样的值


在定义枚举时,是否有关于创建默认值的最佳实践/经验法则?是否应尽可能避免使用它们?

无效的默认值基本上是设计中的一种变体。对象创建时无效。在合理的情况下,你应该避免这样做。你绝不应该“不惜一切代价”避免它

有些问题需要您在变体状态下启动。在这种情况下,必须在心理上对无效值进行推理。如果你避免给它命名,你就在积极地降低代码的表达能力。考虑一下你和以后需要维护代码的人之间的沟通

顺风处理这件事很烦人。您开始时处于变体状态,但到相关时,您希望它不再是变体。我喜欢的策略是允许用户忽略变量状态,在我出错时抛出

namespace FooType {
  enum EnumValue {
    INVALID = 0
    ,valid
  };
}

struct Foo {
  Foo() : val(FooType::INVALID) {}
  FooType::EnumValue get() const {
    if (val == FooType::INVALID)
      throw std::logic_error("variant Foo state");
    return val;
  }
  FooType::EnumValue val;
};
这让你的用户不用为你的差异进行推理,这是值得为之奋斗的

如果你不能摆脱这种情况,我通常倾向于降级为安全和不安全的接口

struct Foo {
  Foo() : val(FooType::INVALID) {}
  bool get(FooType::EnumValue& val_) const {
    if (val == FooType::INVALID)
      return false;
    val_ = val;
    return true;
  }
  FooType::EnumValue get() const {
    FooType::EnumValue val_;
    if (!get(val_))
      throw std::logic_error("variant Foo state");
    return val_;
  }
  FooType::EnumValue get_or_default(FooType::EnumValue def) const {
    FooType::EnumValue val_;
    if (!get(val_))
      return def;
    return val_;
  }
  FooType::EnumValue val;
};

这些类型的接口适用于数据库等可能需要空值的对象。

您可以让您的监控类通过添加监控状态值来“扩展”枚举吗?我可能不完全理解这个建议。在这个特定的示例中,从作业的角度来看,监视_状态仍然没有多大意义,并且根据,我无法扩展监视类中的枚举(理想情况下,它使用eJobStates作为私有变量)。是的,我意识到您无法自然地扩展枚举。监视状态只是一个名称,但您肯定可以使用job\u state\u unknown。我的建议是在监控类中添加额外的enum。您可以通过获取eJobStates的最后一个枚举值并向其添加1来实现这一点,并使其成为监视类的开始枚举状态值。毕竟,使用enum只是比较表示状态的int。如果您想要更具体的东西,那么按照链接中的建议,您可以创建一个枚举类,或者为每个状态创建一个状态对象。