我正在构建一个 Boost 状态机。我的状态有一个指向它自己的后端(fsm
)的指针来处理事件。我的状态机的所有事件都是MySatetMachineEvent
类的子级(带有像EventChild
这样的示例子级)。状态转换仅针对像MySTateMachineEvent
EventChild
这样的孩子定义。
为了清理我的代码,我想创建一个函数processEvent(MySatetMachineEvent event)
获取所有可能的事件。然后,此类应使用传递的事件调用process_event()
函数。 例如:
processEvent(MyStateMachineEvent event)
{
fsm.process_event(event);
}
processEvent(EventCild());
应该调用
fsm.process_event(EventChild());
创建这样的函数会导致错误,即使用MyStateMachineEvent
的实例调用fsm.process_event()
。如上所述,没有为这种情况定义状态转换。
显然,这阻碍了我的状态机以正确的方式工作。
所以我的问题是是否有办法将MyStateMachineEvent
的任何EventChild
或其他子项传递给我的processEvent(MySTateMachineEvent event)
函数,而无需将传递的对象转换为MyStateMachineEvent
。
我知道覆盖我的函数的解决方案,例如
processEvent(EventChild event) {
fsm.process_event(event);
}
在我的情况下,这将导致可能函数(内部具有完全相同的代码行),因此我正在寻找更干净,更花哨的解决方案。
您可以使用函数模板:
template <typename Event>
void processEvent(Event event)
{
fsm.process_event(event);
}
每个实例化都将保留传入的event
参数的确切类型。
尽管我喜欢 Vittorio Romeo 的模板方法,但如果您例如有某种事件队列保存任意事件,它可能不合适。多态方法可能更合适:
class MyStateMachineEvent
{
public:
virtual ~MyStateMachineEvent() { }
virtual void doOrGetSomething() = 0;
};
class EventChild : public MyStateMachineEvent
{
public:
void doOrGetSomething() override;
};
现在你的processEvent
函数可能接受引用,就像fsm
的变体一样:
void processEvent(MyStateMachineEvent& event)
{
fsm.processEvent(event);
}
void FSM::processEvent(MyStateMachineEvent& event)
{
// ...
event.doOrGetSomething();
// ...
}
用法可能如下所示:
std::queue<std::unique_ptr<MyStateMachineEvent>> events;
events.emplace(new EventChild());
processEvent(**events.front());
events.pop();