2010-06-15 1 views
2

Je suis récemment revenu au développement C++ après un hiatus et j'ai une question concernant l'implémentation du modèle de conception d'état. J'utilise le motif de vanille, exactement comme par le livre du GoF.Résolution d'un problème de déclaration anticipée impliquant une machine d'état en C++

Mon problème est que la machine d'état elle-même est basée sur du matériel utilisé dans le cadre d'un système embarqué - la conception est donc fixe et ne peut pas être modifiée. Cela se traduit par une dépendance circulaire entre deux des états (en particulier), et j'essaye de résoudre ce problème . Voici le code simplifié (notez que j'ai essayé de résoudre ce problème en utilisant têtes comme d'habitude, mais encore eu des problèmes - je les ai omis dans cet extrait de code):

#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; 
} 

Le problème est essentiellement que dans le modèle d'État , les transitions d'état sont effectuées par en invoquant la méthode ChangeState dans la classe Context, qui appelle le constructeur de l'état suivant.

En raison de la dépendance circulaire, je ne peux pas invoquer le constructeur car il est impossible de prédéfinir les deux constructeurs des états 'problème'.

J'ai regardé this article, et la méthode de modèle qui semblait être la solution idéale - mais il ne compile pas et ma connaissance des modèles est un peu limité ...

L'autre idée que je Il faut essayer d'introduire une classe Helper dans les états sous-classes, via l'héritage multiple, pour voir s'il est possible de spécifier le constructeur de la classe de base et de faire référence au constructeur de la sous-classe d'état. Mais je pense que c'était plutôt ambitieux ...

Enfin, une implémentation directe du modèle de conception de méthode d'usine serait-elle la meilleure façon de résoudre le problème entier?

Répondre

4

Vous pouvez définir les fonctions membres en dehors des définitions de classe, par exemple,

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

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

Définir les fonctions membres qui reposent sur des définitions de classe plus tard après ces classes sont définies. Le mot clé inline n'est nécessaire que si vous définissez la fonction membre en dehors de de la classe dans le fichier d'en-tête. En outre, pourquoi utilisez-vous simplement new DH() dans vos fonctions? vous fuyez la mémoire partout!

+0

Salut James! Beaucoup, beaucoup merci en effet pour la réponse rapide - qui fonctionne parfaitement :-) Excuses, j'ai oublié de mettre les suppressions correspondantes dans chacun des nouveaux appels() dans l'extrait de code. – HypersonicNinja

+0

@hyper: Pas de problème; Je voulais juste m'assurer que ce n'était pas la seule chose dans tes fonctions ... :-) –

Questions connexes