首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >boost statechart使用转换传递参数

boost statechart使用转换传递参数
EN

Stack Overflow用户
提问于 2011-08-07 02:40:55
回答 2查看 3.2K关注 0票数 4

我正在尝试学习boost::statechart。

我想做一个加载文件的小应用程序。

代码语言:javascript
复制
//  --------------------------------
// |                                |
// |           O     Project        |
// |           |                    |
// |           v                    |
// |  ----------------------------  |
// | |                            | |
// | |         Unloaded           | |
// |  ----------------------------  |
// |  |              ^              |
// |  | EvLoad       | EvUnload     |<-----O
// |  v              |              |
// |  ----------------------------  |
// | |                            | |
// | |         Loaded             | |
// |  ----------------------------  |
// |           |   ^                |
// |           |   | EvLoad         |
// |           -----                |
//  --------------------------------

但是我如何将参数传递给状态,例如文件名?如果我将文件名存储在EvLoad中,我可以很容易地访问它,以便进行in state反应

代码语言:javascript
复制
struct Loaded : sc::simple_state< Loaded, Project>
{
    typedef sc::custom_reaction< EvLoad > reactions;
    sc::result react( const EvLoad & e )
    {
        //load file e.path()
        ...
        return discard_event();
    }
}

但是,当我处于未加载状态时,我调用了已加载的构造函数,并且不能向它传递参数。我想出的唯一解决办法是在进行转换之前重新发布事件,但在我看来这有点脏。

代码语言:javascript
复制
struct Unloaded : sc::simple_state< Unloaded, Project >
{
    typedef sc::custom_reaction< EvLoad > reactions;
     sc::result react( const EvLoad & e )
     {
         post_event( e ); //workaround to pass the event to the loaded state
         return transit<Loaded>();
     }
};

有没有更好的选择?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-07 05:54:24

这句话出自Boost statechart的作者之口,谁还会争辩呢?:)

我的另一个建议是,如果您的任何数据存在于“项目”级别,那么加载的文件名将是FSM状态信息的一部分,处于“项目”级别,而不是“已加载”状态。

您可以使文件名成为EvLoad事件/构造函数的参数,在转换上执行自定义操作,并存储在“项目”上下文中加载的文件名。我认为这更符合statechart的概念。

所以就像这样(尽管我还没有测试过它),显然你会清理它来更好地封装成员:

代码语言:javascript
复制
struct EvLoad: sc::event<EvLoad>
{
    std::string filename;

    EvLoad(const std::string& fn) : filename(fn) {}
};

struct EvUnload: sc::event<EvUnload>

struct Project : sc::state_machine<Project, Unloaded>
{
    std::string filename;

    void LoadFile(const EvLoad& e)
    {
        // Load file
        filename = e.filename;
    }

    void UnloadFile(const EvUnload& e)
    {
        filename.clear();
        // Unload file data
    }
};

struct Unloaded : sc::simple_state<Unloaded, Project>
{
    typedef sc::transition<EvLoad, Loaded, Project, &Project::LoadFile> reactions; 
};

struct Loaded : sc::simple_state<Loaded, Project>
{
    typdef mpl::list<
        sc::transition<EvLoad, Loaded, Project, &Project::LoadFile>,
        sc::transition<EvUnload, Unloaded>
    > reactions;
};

当你加载一个文件时,驱动状态机调用,比如project.process_event(EvLoad(filename));

或者,您可以只将文件名存储在“项目”状态,并从已加载状态使用context().filename访问它。

票数 4
EN

Stack Overflow用户

发布于 2012-03-30 21:00:24

我们使用triggering_event方法拉取触发事件,然后将数据作为成员变量附加到触发事件。它节省了大量的编码工作,并使我们不必生成自定义反应或将转换变量附加到状态图(我见过的两种常见方法)。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6968841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档