Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 状态机表示_C++_State Machine - Fatal编程技术网

C++ 状态机表示

C++ 状态机表示,c++,state-machine,C++,State Machine,我想将GUI实现为一个状态机。我认为这样做有一些好处,也有一些缺点,但这不是这个问题的主题 在阅读了有关这方面的文章后,我发现了几种在C++中建模状态机的方法,我坚持了2种方法,但是我不知道哪种方法能更好地用于GUI建模。 使用以下方法将状态机表示为状态列表: OnEvent(…) onenternstate(…) OnExitState(…) 从StateMachine::OnEvent(…)我将事件转发到CurrentState::OnEvent(…),在这里决定是否进行转换。在转换时,

我想将GUI实现为一个状态机。我认为这样做有一些好处,也有一些缺点,但这不是这个问题的主题

在阅读了有关这方面的文章后,我发现了几种在C++中建模状态机的方法,我坚持了2种方法,但是我不知道哪种方法能更好地用于GUI建模。

  • 使用以下方法将状态机表示为状态列表:

    • OnEvent(…)
    • onenternstate(…)
    • OnExitState(…)
    StateMachine::OnEvent(…)
    我将事件转发到
    CurrentState::OnEvent(…)
    ,在这里决定是否进行转换。在转换时,我调用
    CurrentState::OnExitState(…)
    NewState::oneterstate()
    CurrentState=NewState

    通过这种方法,状态将与动作紧密耦合,但是当我从一个状态转到多个状态,并且我必须为不同的转换采取不同的动作时,
    state
    可能会变得复杂

  • 将状态机表示为具有以下属性的转换列表:

    • InitialState
    • FinalState
    • OnEvent(…)
    • DoTransition(…)
    StateMachine::OnEvent(…)
    I将事件转发到所有转换,其中
    InitialState
    与状态机中的
    CurrentState
    具有相同的值。如果满足转换条件,则循环停止,
    DoTransition
    方法被调用,并且
    CurrentState
    设置为
    transition::FinalState

    使用这种方法,
    转换
    将非常简单,但转换计数的数量可能会非常高。此外,当一个国家收到一个事件时,跟踪将采取的行动也将变得更加困难


  • 您认为哪种方法更适合GUI建模。你知道其他可能更适合我的问题的表示法吗?

    我不知道这是否是你所期望的答案,但我用一种简单的方式处理这种状态机

    使用枚举类型的状态变量(可能的状态)。在GUI的每个事件处理程序中,测试状态值,例如使用switch语句。相应地执行任何需要的处理,并设置状态的下一个值


    轻便灵活。保持代码的规则性使其可读性和“正式”。

    我个人更喜欢你说的第一种方法。我发现第二种方法非常违反直觉,过于复杂。为每个状态设置一个类非常简单,如果您在OneInterState中设置了正确的事件处理程序,并在OnExitState中删除它们,那么您的代码将是干净的,并且所有内容都将在相应的状态中自包含,从而易于阅读

    您还将避免使用大量switch语句来选择要调用的正确事件处理程序或过程,因为状态所做的一切在状态本身内部都是完全可见的,从而使状态机代码简短而简单


    最后但并非最不重要的一点是,这种编码方式是从状态机绘图到您将使用的任何语言的精确转换。

    这里是第三种选择:

    • 将状态机表示为转移矩阵
      • 矩阵列索引表示一个状态
      • 矩阵行索引表示符号(见下文)
      • 矩阵单元表示机器应转换到的状态。这可能是新状态,也可能是同一状态
      • 每个州都有
        OnEvent
        方法,该方法返回一个
        符号
    StateMachine::OnEvent(…)
    事件被转发到
    State::OnEvent
    ,它返回一个
    符号
    ——执行的结果<代码>状态机
    然后根据当前状态和返回的符号决定

    • 必须转换到不同的状态,或者
    • 当前状态被保留
    • 或者,如果进行了转换,则为相应的状态调用
      OnExitState
      oneterstate
    3个状态和3个符号的示例矩阵

    0 1 2
    1 2 0
    2 0 1
    
    在此示例中,如果机器处于任何od状态,则状态
    (0,1,2)
    状态::OnEvent
    返回符号
    0
    (矩阵中的第一行)-它保持在相同的状态

    第二行表示,若当前状态为
    0
    ,返回的符号为
    1
    ,则转换为状态
    1
    。对于状态
    1
    ->状态
    2
    和状态
    2
    ->状态
    0

    类似地,第三行表示符号
    2
    ,状态
    0
    ->状态
    2
    ,状态
    1
    ->状态
    0
    ,状态
    2
    ->状态
    1

    这一点是:

  • 符号的数量可能会比州的数量少得多
  • 各国互不了解
  • 所有转换都是从一个点控制的,因此当您希望以不同的方式处理符号
    DB\u错误
    NETWORK\u错误
    时,您只需更改转换表,而不涉及状态实现

  • 对于这种代码,我更喜欢一种非常简单的方法

    • 国家的列举
    • 每个事件处理程序在决定采取何种操作之前检查当前状态。动作只是
      开关
      语句或
      if
      链中的复合块,并设置下一个状态
    • 当动作的长度超过几行或者需要重用时,重构为调用单独的helper方法
    这样,就没有额外的状态机管理元数据结构,也没有管理元数据的代码。只有您的业务数据和转换逻辑。行动可以