我不断地遇到同样的问题,即使在阅读教程时也无法修复它。我已经“设置”了我的国家机器,但我不能在各州之间过渡。
这是我的StateMachine:
class StateMachine
{
State* m_State;
public:
StateMachine();
~StateMachine();
void changeState(State* state);
};下面是一个例子:
class A : State
{
public:
A();
~A();
void handleInput(int a);
}如果我将a=1传递给A::handleInput(),我希望转换到状态B。但是当我实现它时,我无法从A::handleInput()访问StateMachine,这使我痛苦地擦洗了头。
发布于 2020-10-27 21:53:27
,但是当我实现它时,我无法从
A::handleInput()访问StateMachine
嗯,这是中一个众所周知的问题,没有提到如何使用一个封闭的状态机来跟踪状态类。
IMO,这是将StateMachine类作为实现的有效用例之一。
这样,它的实例就可以从任何State类实现中访问。
正如我在这里所说的设计模式,状态类可以在的帮助下设计,因为它们本身通常是无状态的。
我曾经将所有这些都转化为一个c++模板框架,该框架抽象了状态机和状态机的接口(参见下面的链接)。
下面是一个简短的代码示例:
StateMachine.h
struct State {
virtual void handleInput(int x) = 0;
virtual ~State() {} = 0;
};
class StateMachine {
State* m_State;
StateMachine();
public:
static StateMachine& instance() {
static StateMachine theInstance;
return theInstance;
}
void changeState(State* state) {
m_State = state;
}
void triggerInput(int x) {
m_State->handleInput(x);
}
};StateA.h
#include "StateMachine.h"
class StateB;
extern StateB* stateB;
class StateA : public State {
public:
virtual ~StateA() {}
virtual void handleInput(int x) {
if(x == 1) {
// Change to StateB
StateMachine::instance.changeState(stateB);
}
else {
// Do something with x
}
}
};我在这里省略了StateB的定义,应该和StateA一样。
参考文献:
发布于 2020-10-27 23:04:25
我看了一下源代码生成示例,对我来说,实现示例非常糟糕;必须在每个状态更改上创建新实例:https://sourcemaking.com/design_patterns/state/cpp/1
作为一个用JK触发器在电子领域设计状态机的人,我会使用一种类似但语义不同的方法。状态机中的复杂性涉及到根据状态和输入执行的操作;通常,在C语言中,可以使用大量的开关语句,可能还有描述如何处理current state和new input ( event )的数组。
所以对我来说,面向对象的方法就是对event handler建模。这将有一个接口来描述输入的格式。然后,对于每个不同的状态,您就有了不同的接口实现。这样,状态机就可以简单地将状态集合实现到事件处理程序--数组、向量或映射。虽然处理程序仍然可能包含case语句,但总体的混乱程度大大减少了。您可以在必要时使用新的状态处理程序轻松地扩展设计:
所以你可以有这样的东西:
#include <map>
typedef enum
{
//TODO : state list, e.g.
eOff,
eOn
}
teCurrentState;
typedef struct
{
//TODO : Add inputs here, e.g.
bool switch1;
}
tsInputDesc;
typedef struct
{
//TODO : Add outputs here, e.g.
bool relay1;
}
tsOutputDesc;
// ------------------------------------------------
class IEventHandler
{
public:
virtual ~IEventHandler() {}
// returns new state
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) = 0;
};
// ------------------------------------------------
class OnStateHandler : public IEventHandler
{
public:
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) override
{
//TODO : IMPLEMENT
teCurrentState newState = TODO....
return (newState);
}
};
// ------------------------------------------------
class OffStateHandler : public IEventHandler
{
public:
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) override
{
//TODO : IMPLEMENT
teCurrentState newState = TODO....
return (newState);
}
};
// ------------------------------------------------
class StateMachine
{
protected:
teCurrentState mCurrentState;
std::map<teCurrentState, IEventHandler*> mStateHandlers;
void makeHandlers()
{
mStateHandlers[eOff] = new OffStateHandler();
mStateHandlers[eOn] = new OnStateHandler();
}
public:
StateMachine()
{
makeHandlers();
mCurrentState = eOff;
}
void handleInput(tsInputDesc const& input, tsOutputDesc output)
{
teCurrentState newState = mStateHandlers[mCurrentState]->handleInput(input, output);
mCurrentState = newState;
}
};
// ------------------------------------------------
void runFsm()
{
StateMachine fsm;
tsInputDesc input;
tsOutputDesc output;
bool alive = true;
while (alive)
{
// TODO : set input according to....inputs (e.g. read I/O port etc)
fsm.handleInput(input, output);
// TODO : use output
}
}https://stackoverflow.com/questions/64563173
复制相似问题