【问题标题】:Resolving a Forward Declaration Issue Involving a State Machine in C++在 C++ 中解决涉及状态机的前向声明问题
【发布时间】:2011-03-03 23:52:51
【问题描述】:

我最近在中断后回到 C++ 开发,并且有一个关于 状态设计模式的实现。我正在使用香草模式,完全一样 根据 GoF 的书。

我的问题是状态机本身是基于一些用作 嵌入式系统 - 因此设计是固定的,无法更改。这导致一个 两个状态之间的循环依赖(特别是),我正在尝试 解决这个问题。这是简化的代码(请注意,我尝试通过使用来解决此问题 像往常一样的标题但仍然有问题 - 我在这段代码中省略了它们 sn-p):

#include <iostream>
#include <memory>

using namespace std;

class Context
{
public:
    friend class State;

    Context() { }

private:
    State* m_state;
};

class State
{
public:
    State() { }

    virtual void Trigger1() = 0;
    virtual void Trigger2() = 0;
};

class LLT : public State
{
public:
    LLT() { }
    void Trigger1() { new DH(); }
    void Trigger2() { new DL(); }
};


class ALL : public State
{       
public: 
    ALL() { }
    void Trigger1() { new LLT(); }
    void Trigger2() { new DH();  }
};  

// DL needs to 'know' about DH.
class DL  : public State
{           
public:
    DL() { }
    void Trigger1() { new ALL(); }
    void Trigger2() { new DH();  }
};      

class HLT :  public State
{
public:
    HLT() { }
    void Trigger1() { new DH(); }
    void Trigger2() { new DL(); }
};

class AHL : public State
{
public:
    AHL() { }
    void Trigger1() { new DH();  }
    void Trigger2() { new HLT(); }
};

// DH needs to 'know' about DL.
class DH  : public State
{
public:
    DH () { }
    void Trigger1() { new AHL(); }
    void Trigger2() { new DL();  }
};


int main()
{
    auto_ptr<LLT> llt (new LLT);
    auto_ptr<ALL> all (new ALL);
    auto_ptr<DL>  dl (new DL);
    auto_ptr<HLT> hlt (new HLT);
    auto_ptr<AHL> ahl (new AHL);
    auto_ptr<DH>  dh (new DH);  

    return 0;
}

问题基本上是在状态模式中,状态转换是由 调用 Context 类中的 ChangeState 方法,该方法调用 下一个状态的构造函数。

由于循环依赖,我无法调用构造函数,因为它是 无法预先定义“问题”状态的两个构造函数。

我查看了this 文章,模板方法似乎是理想的解决方案 - 但它无法编译,而且我对模板的了解相当有限......

我的另一个想法是尝试将 Helper 类引入子类状态, 通过多重继承,看看是否可以指定基类的构造函数 并引用状态子类的构造函数。但我认为那是相当 雄心勃勃...

最后,工厂方法设计模式的直接实现会是最好的方法吗? 解决整个问题?

【问题讨论】:

    标签: c++ design-patterns circular-dependency forward-declaration state-pattern


    【解决方案1】:

    您可以在类定义之外定义成员函数,例如,

    class DL : public State
    {
    public:
        void Trigger2();
    };
    
    inline void DL::Trigger2() { new DH(); }
    

    定义依赖于以后的类定义的成员函数这些类被定义之后。 inline关键字只有在头文件中定义类的成员函数outside时才需要。

    顺便说一句,你为什么只在你的函数中使用new DH();你到处都在泄漏内存!

    【讨论】:

    • 嗨詹姆斯!非常非常感谢您的快速回答 - 效果很好:-) 抱歉,我忘记在代码 sn-p 中为每个 new() 调用添加相应的删除。
    • @hyper:没问题;我只是想确保这不是你的函数中的 only 东西...... :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    相关资源
    最近更新 更多