Qt状态机中如何实现选择分支?有没有更易维护的实现方案?
最优实现方案
Qt的状态机框架本身已经提供了足够灵活的扩展能力,你只需要实现1次通用的条件过渡类,之后所有选择逻辑都可以直接复用,不需要重复编写子类。
第一步:实现通用可复用的条件过渡类
#include <QAbstractTransition> #include <functional> class ConditionTransition : public QAbstractTransition { public: explicit ConditionTransition(std::function<bool()> judgeFunc, QState *source = nullptr) : QAbstractTransition(source), m_judge(std::move(judgeFunc)) {} protected: // 过渡触发判断逻辑 bool eventTest(QEvent *event) override { Q_UNUSED(event) return m_judge ? m_judge() : false; } void onTransition(QEvent *event) override { Q_UNUSED(event) } private: std::function<bool()> m_judge; };
第二步:直接使用该类实现选择逻辑
你只需要给状态S1添加两个该类的实例,分别对应判断条件为真/假的分支即可:
// 示例:假设已经初始化好了状态S1、S2、S3,以及判断函数checkCondition() // 条件为真时跳转到S2 auto *trueBranch = new ConditionTransition(checkCondition); trueBranch->setTargetState(S2); S1->addTransition(trueBranch); // 条件为假时跳转到S3 auto *falseBranch = new ConditionTransition([]{ return !checkCondition(); }); falseBranch->setTargetState(S3); S1->addTransition(falseBranch);
更简化的场景方案
如果你的选择逻辑不需要等待额外事件触发,是进入S1后立刻执行判断,还可以省去自定义过渡类的步骤:
// 绑定S1的进入信号,直接判断后切换状态 connect(S1, &QState::entered, [=]{ checkCondition() ? S1->machine()->setCurrentState(S2) : S1->machine()->setCurrentState(S3); });
基于信号触发的选择方案
如果选择逻辑是在收到某个特定信号后触发,你连自定义类都不需要,直接用QSignalTransition自带的守卫功能即可:
// 示例:当对象obj发出ready()信号时执行选择判断 auto *trueBranch = new QSignalTransition(obj, &YourClass::ready); trueBranch->setGuard(checkCondition); trueBranch->setTargetState(S2); S1->addTransition(trueBranch); auto *falseBranch = new QSignalTransition(obj, &YourClass::ready); falseBranch->setGuard([]{ return !checkCondition(); }); falseBranch->setTargetState(S3); S1->addTransition(falseBranch);
以上几种方案都只需要写一次通用逻辑,后续所有选择场景都可以直接复用,不会出现重复编写子类的冗余问题,维护成本极低。
内容的提问来源于stack exchange,提问作者Tim Meyer
相关产品推荐
相关产品推荐

