【问题标题】:Using ranges of an enum for simple state tracking使用枚举范围进行简单的状态跟踪
【发布时间】:2021-03-12 05:41:05
【问题描述】:

我正在使用一系列用于嵌入式系统状态管理的枚举。

我现在正在实施的是一个系统,可以以简单的方式向用户显示特定模块的状态。所以我想把这些不同的状态翻译成 3 个超级状态,在这种情况下红色/黄色/绿色表示错误/配置/运行。

到目前为止,我实现它的简单方法如下。

enum State
{
  StateAA = 0,
  StateAB,
  StateAC,
  
  StateBA = 100,
  StateBB,
  StateBC,
  
  StateCA = 200,
  StateCB
};

void DisplayState(State st)
{
    if(st < 100)
        displayColor = red;
    else if(st < 200)
        displayColor = yellow;
    else
        displayColor = green;
}

这允许在不调整显示功能的情况下管理对枚举的更改,只要范围没有更改。

但是,这感觉有点老套,而且我很难用措辞来找到更好的答案。任何建议将不胜感激。

【问题讨论】:

    标签: c++ embedded c++98


    【解决方案1】:

    这看起来确实很“骇人听闻”。而是考虑使用状态机,其中每个状态依次使用自己的内部状态机。这个内部状态应该与程序的其余部分无关,而是被私有封装。

    还要避免手动为枚举赋值,如果你不这样做,那么你可以使用枚举类型作为数组索引,这很方便。如果你不这样做,你也可以在最后使用State_n 成员的老派技巧,然后对应于使用的状态数。 (轮到可以static_assert 对抗数组等以确保程序完整性。)

    【讨论】:

      【解决方案2】:

      我建议在switch 中使用“失败”案例:

      enum State
      {
        StateAA,
        StateAB,
        StateAC,
        
        StateBA,
        StateBB,
        StateBC,
        
        StateCA,
        StateCB
      };
      
      void DisplayState(State st)
      {
        switch( st )
        {
            case StateAA :
            case StateAB :
            case StateAC :
            {
               displayColor = red;
            }
            break ;
      
            case StateBA :
            case StateBB :
            case StateBC :
            {
               displayColor = yellow;
            }
            break ;
        
            case StateCA :
            case StateCB :
            default :
            {
              displayColor = green;
            }
            break ;
         }
      }
      

      这样,每个案例的枚举不必是连续的或在特定范围内。

      如果您选择不这样做,至少在条件中使用enum 常量而不是“幻数”:

      if(st < StateBA)
          displayColor = red;
      else if(st < StateCA)
          displayColor = yellow;
      else
          displayColor = green;
      

      或者更好的是,在枚举中定义组:

      enum State
      {
        StateAA,
        StateAB,
        StateAC,
      
        StateB_GroupStart,
        StateBA = StateB_GroupStart,
        StateBB,
        StateBC,
      
        StateC_GroupStart,
        StateCA = StateC_GroupStart,
        StateCB
      };
      

      然后:

      if(st < StateB_GroupStart)
          displayColor = red;
      else if(st < StateC_GroupStart)
          displayColor = yellow;
      else
          displayColor = green;
      

      我不能真正推荐这最后两个选项中的任何一个 - 它们只是比您的原始解决方案更不“hacky”。它们仍然依赖于 enum 常量的特定顺序,如果您不知道它很关键,这可能很容易在维护中搞砸——它至少需要一个注释来阻止粗心的维护者破坏它。您可以通过定义组结束广告测试 st 介于开始和结束之间来在一定程度上缓解这种情况,但这只是说明了解决方案的麻烦程度。我还需要一个通常效率较低的if/else if/else 链。

      通过避免在enum 值中产生“间隙”,以便每个连续值是连续的,这意味着可以轻松地将开关优化为跳转表。如果您在条件测试中使用enum 常量,那么这些间隙在任何情况下都是不必要的。

      【讨论】:

        猜你喜欢
        • 2010-11-27
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        • 2011-11-06
        • 1970-01-01
        • 1970-01-01
        • 2011-10-16
        • 1970-01-01
        相关资源
        最近更新 更多