子类化和修改 QStateMachine

Subclassing and modifying QStateMachine

假设我有一群 运行 一个 QStateMachine 的机器人。这些机器人的所有状态机都具有相同的基本结构:

// base.h

#include <QObject>
#include <QState>
#include <QStateMachine>

class Base : public QObject
{
    Q_OBJECT
public:
    Base(QObject* parent = 0);
    ~Base();

signals:
    void next();
    void back();

private:
    QStateMachine m_machine;
    QState* m_sleep;
    QState* m_search;
    QState* m_destroy;
    QState* m_return;
};

// base.cpp

Base::Base(QObject* parent) : QObject(parent)
{
    m_sleep = new QState(&m_machine);
    m_search = new QState(&m_machine);
    m_destroy = new QState(&m_machine);
    m_return = new QState(&m_machine);

    m_machine.setInitialState(m_sleep);

    m_sleep->addTransition(this, &Base::next, m_search);
    m_search->addTransition(this, &Base::next, m_destroy);
    m_search->addTransition(this, &Base::back, m_return);
    m_destroy->addTransition(this, &Base::next, m_search);
    m_destroy->addTransition(this, &Base::back, m_return);
    m_return->addTransition(this, &Base::next, m_search);
    m_return->addTransition(this, &Base::back, m_sleep);

    m_machine.start();
}

现在我想要一个可能更具体一点的机器人。假设他在破坏过程中更加详细,具有几个子状态,例如dismantel -> sprayWithAcid -> blowUp -> desintegrate,他在每个 next-信号时继续前进,或者他在 back-信号时继续 return

如前所述,我的计划是将它们作为子状态添加到状态 destroy,但由于信号 next 不仅会继续子状态机直到完成,还会离开父状态.

我怎样才能避免这种情况? 或者有其他类似的好方法吗?

我明白了。

诀窍是显式创建转换,将它们作为 class 的成员。您可以这样设置它们:

m_sleepSearch = new QSignalTransition(this, &Base::next, m_sleep);
m_searchDestroy = new QSignalTransition(this, &Base::next, m_search);
m_searchReturn = new QSignalTransition(this, &Base::back, m_search);
m_destroySearch = new QSignalTransition(this, &Base::next, m_destroy);
m_destroyReturn = new QSignalTransition(this, &Base::back, m_destroy);
m_returnSearch = new QSignalTransition(this, &Base::next, m_return);
m_returnSleep = new QSignalTransition(this, &Base::back, m_return);

m_sleepSearch->setTargetState(m_search);
m_searchDestroy->setTargetState(m_destroy);
m_searchReturn->setTargetState(m_return);
m_destroySearch->setTargetState(m_search);
m_destroyReturn->setTargetState(m_return);
m_returnSearch->setTargetState(m_search);
m_returnSleep->setTargetState(m_sleep);

我首先出错的是 QSignalTransition(sender, signal, source_state) 构造函数的参数错误,因为它与 ->addTransition(sender, signal, target_state) 的语法太相似了,所以我混淆了 sourcetarget.

像这样创建它们之后,当子class这个对象时,重新路由或禁用其中一些转换应该很容易。