如何在Boost.MSM子状态机中访问外层状态机的上下文?
Boost.MSM内部状态机访问外层上下文的实现方案
核心解决思路
Boost.MSM的内部状态机可以通过外层状态机的引用直接访问上下文,关键是利用状态回调(如on_entry/on_exit)或动作函数中的SM&参数——这个参数实际指向包含该内部状态机的外层状态机实例,通过它就能获取外层的上下文对象。
具体实现方式
1. 直接通过外层状态机引用访问上下文
在内部状态机的回调或动作中,使用传入的SM&参数直接访问外层状态机的m_component成员:
struct ComponentStateMachine_ : public msm::front::state_machine_def<ComponentStateMachine_> { public: TrajectoryManagerComponent* m_component; void link_component(hyro::guidance::TrajectoryManagerComponent* component) { m_component = component; } struct Operating_ : public msm::front::state_machine_def<Operating_> { template <typename Event, typename SM> void on_entry(Event const&, SM& outer_fsm) { if (outer_fsm.m_component) { // 直接调用组件方法 outer_fsm.m_component->invoke_your_method(); m_logger->info("Accessing component, address: {}", outer_fsm.m_component); } } // 子状态中同样适用 struct SubState1 : public msm::front::state<> { template <typename Event, typename SM> void on_entry(Event const&, SM& outer_fsm) { outer_fsm.m_component->another_method(); } }; }; };
2. 确保上下文提前初始化
外层状态机的link_component方法必须在状态机启动前调用,保证m_component不为空:
// 实例化外层状态机并绑定上下文 ComponentStateMachine outer_fsm; outer_fsm.link_component(&your_trajectory_component_instance); outer_fsm.start();
3. 可选:封装上下文访问接口(提升封装性)
如果不想直接暴露外层状态机的成员变量,可以在外层状态机中封装一个获取上下文的方法:
struct ComponentStateMachine_ : public msm::front::state_machine_def<ComponentStateMachine_> { public: TrajectoryManagerComponent* m_component; void link_component(hyro::guidance::TrajectoryManagerComponent* component) { m_component = component; } // 封装上下文获取接口 TrajectoryManagerComponent* get_component() const { return m_component; } struct Operating_ : public msm::front::state_machine_def<Operating_> { template <typename Event, typename SM> void on_entry(Event const&, SM& outer_fsm) { auto component = outer_fsm.get_component(); if (component) { component->invoke_your_method(); } } }; };
不推荐的替代方案
若上述方式不适用,也可以将TrajectoryManagerComponent设为全局变量或单例,但这种方式会大幅降低代码的可测试性和可维护性,仅适合极端场景使用。
内容的提问来源于stack exchange,提问作者Daniel Andrade
相关产品推荐
相关产品推荐

