c++ - 状态机实现

标签 c++ state-machine

我有一个状态机,如下所述。

我们可以从两个起始状态之一开始,但我们必须达到握手的所有 4 个状态。从那里,我们可以传输数据有效负载或接收数据有效负载。然后,我们回到原来的起始状态。

握手:

-> StartingState1 -> FinalState1 -> StartingState2 -> FinalState2

-> StartingState2 -> FinalState2 -> StartingState1 -> FinalState1

有效载荷传输:

-> SendPayload -> SendEnd -> StartingState?

-> ReceivePayload -> ReceiveEnd -> StartingState?

下面的代码代表了我当前的架构。不幸的是,在每个过程结束时,我没有足够的状态内部信息来知道我应该达到的下一个状态。

有没有人对如何根据我的要求改进此架构有任何建议?

谢谢, 保罗H

class MyMachine;
class Payload;

class IState
{
    MyMachine* context_;

    IState( MyMachine* context ) : context_( context) {};

    virtual void Consume( byte data );

    void ChangeState( IState* state )
    {
        context_->SetState( state );
    }
}

class FinalState1 : IState
{
    void Consume( byte data )
    {
        // Either go to StartingState1, SendPayload, or ReceivePayload.
        // How can I tell from within the context of this state where I 
        // should go?
    }
}

class StartingState1 : IState
{
    void Consume( byte data )
    {
        if ( /*some condition*/ )
        {
            ChangeState( new FinalState1( context_ ) );
        } 
    }
}

class MyMachine
{
    IState* state_;
    Payload* payload_;

    void Start1( Mode mode )
    {
        state_ = new StartingState1( this );
    }

    void Start2( Mode mode )
    {
        state_ = new StartingState2( this );
    }

    void Consume( byte data )
    {
        state_->Consume( data );
    }

    void SetPayload( const Payload* payload )
    {
        payload_ = payload;
    }

    const Payload* GetPayload()
    {
        return payload_;
    }

    void SetState( State* state )
    {
        delete state_;
        state_ = state;
    }
}

// get a byte of data from some source
byte GetData();

void main()
{
    MyMachine machine;
    Payload payload;
    machine.SetPayload( payload );
    machine.Start1( Mode::SendPayload );

    // could also call:
    // machine.Start1( Mode::ReceivePayload );
    // machine.Start2( Mode::SendPayload );
    // machine.Start2( Mode::ReceivePayload );

    for(;;)
    {
        machine.Consume( GetData() );
    }
}

最佳答案

您所拥有的并不能完全代表系统的可能状态,但很容易对其进行转换,使其能够代表系统的状态。您需要其他状态来表示处于状态 1 和未处于状态 2 以及处于状态 1 但处于状态 2(状态 2 相同)之间的区别。所以你需要:

S1 S2 F1 F2 S12 F12 S21 F21
SP SE
RP RE

有过渡

S1 --> F1
F1 --> S12
S12 --> F12
F12 --> SP or F12 --> RP

S2 --> F2
F2 --> S21
S21 --> F21
F21 --> SP or F21 --> RP

SP --> SE
RP --> RE
SE --> S1 or SE --> S2
RE --> S1 or RE --> S2

主要区别在于引入了新状态 S12F12S21F21。在实现方面,您几乎可以肯定地从 S2 派生 S12,从 F2 派生 F12,从 S1 派生 S21,从 F2 派生 F21,然后覆盖转换函数以进入正确的状态。

(很抱歉将您所有的州缩写)。

关于c++ - 状态机实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2180368/

相关文章:

amazon-web-services - 状态机忽略阶跃函数错误

c# - 在枚举中明确定义标志组合

uml - uml 状态机图中的 if 条件

c++ - 我如何知道 Boost 的哪些部分已被弃用?

C++:我无法开始我的类(class),我得到类未在此范围内声明的错误

c++ - 在 C++ 中及时求解 ODE 系统

statistics - 隐马尔可夫模型

c - 在没有数组的长序列中搜索模式字符串

c++ - namespace 的可见性问题

c++ - 如何通过 << 运算符将参数传递给函数?