Gra*_*ant 7 c++ boost boost-statechart
我希望有人可以帮我解决这个问题,或者至少指出我的方式错误......
作为我的问题的简单说明,考虑应用程序的一部分,您可以在其中进入"功能模式"操作状态.然后,取决于用户按下哪个功能键F1-F4,可以使用四个子模式.默认情况下,输入F1模式.状态图从如下开始:

用户可以随时按F1-F4切换到相应的模式.将这些转换添加到内部状态会导致以下情况:

显然这是(a)一团糟,(b)要定义的很多过渡.如果在某些时候我想添加一个F5Mode然后......好吧,你得到了图片.为避免这种情况,我想做以下事情:

Boost Statechart允许我定义从FunctionMode到任何内部状态的转换,但结果不是我所期望的.实际结果如下:

即按F1-F4切换模式会导致外部FunctionMode状态退出并重新进入,同时触发不需要的退出和进入操作.
早在2006年,图书馆作者和用户之间的这个线程似乎描述了同样的问题.我认为作者建议做以下工作:
然而,这种解决方法对我来说似乎并不吸引人:它已经添加了一个额外的状态级别来编译,代码变得不那么可读,深度历史将不得不用于返回任何功能模式子-states和中间状态对象不必要地被破坏并再次构造.
那么......我哪里错了?或者有哪些替代方案?我已经简要介绍了Boost Meta State Machine(msm),但从我到目前为止看到的情况来看,我更喜欢Statechart的外观.
我很惊讶更多的用户没有遇到同样的问题......这让我觉得我的方法可能完全错了!
您是否看过状态图教程中解释的状态反应?它似乎正在做你正在寻找的事情。
由于您正在寻求替代方案,因此在此期间我正在评估各种 C++ Harel 状态图实现。我查看了 Boost 状态图和 Boost MSM。我用两者编写了代码。他们伤害了我脆弱的大脑:-)
然后我发现了Machine Objects (Macho),非常简单而且很小,我喜欢它。它支持分层状态机、进入/退出操作、历史记录、状态机快照、防护、内部转换、事件延迟、状态本地存储(具有可选的持久性),所以对我来说,这是一个令人满意的 Harel 状态图实现。
此代码使用 Macho 实现状态图的 FunctionMode 部分:
#include "Macho.hpp"
#include <exception>
#include <iostream>
using namespace std;
namespace FunctionMode {
struct FunctionMode;
struct F1Mode;
struct F2Mode;
// The Top state, containing all the others.
TOPSTATE(Top) {
STATE(Top)
// All the events of the state machine are just virtual functions.
// Here we throw to mean that no inner state has implemented the event
// handler and we consider that an error. This is optional, we could
// just have an empty body or log the error.
virtual void evF1() { throw std::exception(); }
virtual void evF2() { throw std::exception(); }
// evF3 and so on...
private:
void init() { setState<FunctionMode>(); } // initial transition
};
SUBSTATE(FunctionMode, Top) {
STATE(FunctionMode)
virtual void evF1() { setState<F1Mode>(); }
virtual void evF2() { setState<F2Mode>(); }
// evF3, ...
private:
void entry() { cout << "FunctionMode::entry" << endl; }
void exit() { cout << "FunctionMode::exit" << endl; }
void init() { setState<F1Mode>(); } // initial transition
};
SUBSTATE(F1Mode, FunctionMode) {
STATE(F1Mode)
virtual void evF1() {} // make the event an internal transition (by swallowing it)
private:
void entry() { cout << "F1Mode::entry" << endl; }
void exit() { cout << "F1Mode::exit" << endl; }
};
SUBSTATE(F2Mode, FunctionMode) {
STATE(F2Mode)
virtual void evF2() {} // make the event an internal transition (by swallowing it)
private:
void entry() { cout << "F2Mode::entry" << endl; }
void exit() { cout << "F2Mode::exit" << endl; }
};
} // namespace FunctionMode
int main() {
Macho::Machine<FunctionMode::Top> sm;
// Now the machine is already in F1Mode.
// Macho has 2 methods for synchronous event dispatching:
// First method:
sm->evF1(); // <= this one will be swallowed by F1Mode::evF1()
// Second method:
sm.dispatch(Event(&FunctionMode::Top::evF2));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行它,输出是:
FunctionMode::entry
F1Mode::entry
F1Mode::exit
F2Mode::entry
F2Mode::exit
FunctionMode::exit
Run Code Online (Sandbox Code Playgroud)
这表明转变是内部的。
在我看来,干净、简单、紧凑的代码:-)
[EDIT1] 代码的第一个版本没有执行初始转换FunctionMode-> F1Mode。现在确实如此。
| 归档时间: |
|
| 查看次数: |
1774 次 |
| 最近记录: |