Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Design Pattern Etat

6 réponses
Avatar
ByB
Bonjour,

J'ai essayé de développer une petite application mettant en oeuvre le
Design Pattern Etat (à titre d'exercice), mais je rencontre qques
difficultés (note : je travaille avec Visual C++ 6.0) :

Mon but est de modéliser le fonctionnement d'un feu rouge. J'ai donc
créé une classe MonFeuRouge, une classe Etat et trois classes
EtatRouge, EtatOrange et EtatVert.
Dans le fichier Stdafx.h (ou je place d'habitude les #include
nécessaire à tout le projet) j'ai placé :

#include "Etat.h"
#include "EtatRouge.h"
#include "EtatOrange.h"
#include "EtatVert.h"
#include "MonFeuRouge.h"

Dans la classe Etat.h (dont dérivent les 3 états), j'ai défini une
méthode :

virtual void ChangeEtat() = 0;

Et j'ai implémenté cette méthode dans les trois classes EtatRouge,
EtatOrange et EtatVert.

(Méthode définie ainsi dans les fichier .h
void ChangeEtat();

et implémentée ainsi :
void ChangeEtat()
{


}
dans les fichier .cpp)

Je rencontre plusieurs problèmes :

a) Quand je compile, je reçois des messages d'erreur au link :

tatRouge.obj : error LNK2005: "void __cdecl ChangeEtat(void)"
(?ChangeEtat@@YAXXZ) already defined in EtatOrange.obj
EtatVert.obj : error LNK2005: "void __cdecl ChangeEtat(void)"
(?ChangeEtat@@YAXXZ) already defined in EtatOrange.obj
EtatOrange.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatOrange::ChangeEtat(void)"
(?ChangeEtat@EtatOrange@@UAEXXZ)
EtatRouge.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatRouge::ChangeEtat(void)"
(?ChangeEtat@EtatRouge@@UAEXXZ)
EtatVert.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatVert::ChangeEtat(void)"
(?ChangeEtat@EtatVert@@UAEXXZ)
Debug/FeuRouge.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

b) Si je comprend bien le DP Etat, la classe MonFeuRouge doit avoir un
pointeur sur un objet Etat, et les trois Etats doivent avoir un
pointeur vers MonFeuRouge.

Dans ces conditions, dans quel ordre faut-il effectuer les #include
dans le fichier stdafx.h, puisque chaque classe doit connaitre l'autre
?

Merci de vos conseils ! :-)






--
L'IMAGINATION RENOUVELLE LES PROCESSUS STRATEGIQUES DES STRUCTURES

6 réponses

Avatar
Aurélien Barbier-Accary
Bonjour,

J'ai essayé de développer une petite application mettant en oeuvre le
Design Pattern Etat (à titre d'exercice), mais je rencontre qques
difficultés (note : je travaille avec Visual C++ 6.0) :

Mon but est de modéliser le fonctionnement d'un feu rouge. J'ai donc
créé une classe MonFeuRouge, une classe Etat et trois classes EtatRouge,
EtatOrange et EtatVert.
Dans le fichier Stdafx.h (ou je place d'habitude les #include nécessaire
à tout le projet) j'ai placé :

#include "Etat.h"
#include "EtatRouge.h"
#include "EtatOrange.h"
#include "EtatVert.h"
#include "MonFeuRouge.h"

Dans la classe Etat.h (dont dérivent les 3 états), j'ai défini une
méthode :

virtual void ChangeEtat() = 0;

Et j'ai implémenté cette méthode dans les trois classes EtatRouge,
EtatOrange et EtatVert.

(Méthode définie ainsi dans les fichier .h
void ChangeEtat();

et implémentée ainsi :
void ChangeEtat()
{


}
dans les fichier .cpp)

Je rencontre plusieurs problèmes :

a) Quand je compile, je reçois des messages d'erreur au link :

tatRouge.obj : error LNK2005: "void __cdecl ChangeEtat(void)"
(?ChangeEtat@@YAXXZ) already defined in EtatOrange.obj
EtatVert.obj : error LNK2005: "void __cdecl ChangeEtat(void)"
(?ChangeEtat@@YAXXZ) already defined in EtatOrange.obj
EtatOrange.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatOrange::ChangeEtat(void)"
(?@@UAEXXZ)
EtatRouge.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatRouge::ChangeEtat(void)"
(?@@UAEXXZ)
EtatVert.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall EtatVert::ChangeEtat(void)"
(?@@UAEXXZ)
Debug/FeuRouge.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

b) Si je comprend bien le DP Etat, la classe MonFeuRouge doit avoir un
pointeur sur un objet Etat, et les trois Etats doivent avoir un pointeur
vers MonFeuRouge.

Dans ces conditions, dans quel ordre faut-il effectuer les #include dans
le fichier stdafx.h, puisque chaque classe doit connaitre l'autre ?

Merci de vos conseils ! :-)




Je n'ai pas tout bien compris mais si tu as 3 classes qui ressemble à ça :

class EtatRouge | classEtatOrange | classEtatVert
{ | { | {
//... | //... | //...
void ChangeEtat(); | void ChangeEtat(); | void ChangeEtat();
//... | //... | //...
}; | }; | };

alors dans ton fichier EtatRouge .cpp tu dois implémenter

void EtatRouge::ChangeEtat() et pas void ChangeEtat()
// ^^^^^^^^^^^ // ^^^
{ {
//... ...
} }

et faire de même dans tes fichiers EtatOrange.cpp et EtatVert.cpp puisque tu
dois implémenter la méthode ChangeEtat *de la classe EtatRouge* (respectivement
EtatOrange et EtatVert).

Pour la partie b) j'avoue que je ne comprends pas bien ta question mais j'espère
que ceci te permettra déjà d'avancer.

Aurélien.

Avatar
Aurélien Barbier-Accary

Dans ces conditions, dans quel ordre faut-il effectuer les #include
dans le fichier stdafx.h, puisque chaque classe doit connaitre l'autre ?




Comme je l'ai dit précédemment je ne suis pas sûr de comprendre ta question mais
peut-être que l'exemple simple ci-dessous pourra t'aider :

class cA
{
cB unB;
//...
};

class cB
{
cA unA;
//...
};

Quel que soit l'ordre de déclaration des classes, ça bloque.
Pour résoudre ça on déclare juste le prototype de la classe C
cB avant de définir cA comme suit :

class cB;

class cA
{
cB unB;
//...
};

class cB
{
cA unA;
//...
};

Le fait de définir les différentes classes dans différents fichiers .h ne change
rien au problème ni à la solution. I faut juste bien penser (comme toujours) à
mettre *tout le code* des .h entre des commandes :

#ifndef _NOM_DE_CE_FICHIER_H_
#define _NOM_DE_CE_FICHIER_H_

et

#endif

J'espère ne pas être trop à côté de la plaque de tes interrogations.
Si c'est le cas, désolé :-)
Aurélien.


Avatar
ByB
Si Aurélien Barbier-Accary ne nous l'avait pas dit, on n'aurait jamais
cru que


Je n'ai pas tout bien compris mais si tu as 3 classes qui ressemble à ça :

class EtatRouge | classEtatOrange | classEtatVert
{ | { | {
//... | //... | //...
void ChangeEtat(); | void ChangeEtat(); | void ChangeEtat();
//... | //... | //...
}; | }; | };

alors dans ton fichier EtatRouge .cpp tu dois implémenter

void EtatRouge::ChangeEtat() et pas void ChangeEtat()
// ^^^^^^^^^^^ // ^^^
{ {
//... ...
} }

et faire de même dans tes fichiers EtatOrange.cpp et EtatVert.cpp puisque tu
dois implémenter la méthode ChangeEtat *de la classe EtatRouge*
(respectivement EtatOrange et EtatVert).

Pour la partie b) j'avoue que je ne comprends pas bien ta question mais
j'espère que ceci te permettra déjà d'avancer.

Aurélien.


OK, c'était bien le problème, merci.




--
Le comble de la prudence :
Marcher sur les mains, de peur de recevoir une tuile sur la tête.
[Alphonse Allais]

Avatar
ByB
Mieux que du Shakespeare, c'est le message de Aurélien Barbier-Accary
qui affirme :

Dans ces conditions, dans quel ordre faut-il effectuer les #include dans
le fichier stdafx.h, puisque chaque classe doit connaitre l'autre ?




Comme je l'ai dit précédemment je ne suis pas sûr de comprendre ta question
mais peut-être que l'exemple simple ci-dessous pourra t'aider :

class cA
{
cB unB;
//...
};

class cB
{
cA unA;
//...
};

Quel que soit l'ordre de déclaration des classes, ça bloque.
Pour résoudre ça on déclare juste le prototype de la classe C
cB avant de définir cA comme suit :

class cB;

class cA
{
cB unB;
//...
};

class cB
{
cA unA;
//...
};

Le fait de définir les différentes classes dans différents fichiers .h ne
change rien au problème ni à la solution. I faut juste bien penser (comme
toujours) à mettre *tout le code* des .h entre des commandes :

#ifndef _NOM_DE_CE_FICHIER_H_
#define _NOM_DE_CE_FICHIER_H_

et

#endif

J'espère ne pas être trop à côté de la plaque de tes interrogations.
Si c'est le cas, désolé :-)
Aurélien.


C'était bien cela également, merci ! :-)

--
Championnat du millimètre à vélocipède : record mondial actuellement
détenu par le Captain Cap en 1/17.000ème de seconde (Alphonse Allais)



Avatar
Yoxoman
Aurélien Barbier-Accary a écrit
:

Pour résoudre ça on déclare juste le prototype de la classe C
cB avant de définir cA comme suit :

class cB;

class cA
{
cB unB;
//...
};


Il me semble que dans cA, on ne peut manipuler cB qu'à travers un
pointeur ou une référence, pour éviter de tourner en rond. Me trompe-je
?

class cB
{
cA unA;
//...
};



--
"Yo!"
Martin Heidegger

Avatar
Aurélien Barbier-Accary
Il me semble que dans cA, on ne peut manipuler cB qu'à travers un
pointeur ou une référence, pour éviter de tourner en rond. Me trompe-je
?



:-O
Effectivement, merci.