IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

architecture c++ Parent <> enfants sans dynamic_cast


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 37
    Points : 28
    Points
    28
    Par défaut architecture c++ Parent <> enfants sans dynamic_cast
    Bonjour,

    Je suis en train de mettre en place une architecture parent <> enfants, et ne trouve pas de methode de recherche sans utilisation de dynamic cast.

    je m'explique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    class Object
    {
    public:
      Object(void);
      virtual ~Object(void);
     
      virtual const std::string& GetName(void){return m_Name;}
     
      template <class T>
      int Find(std::string Name, std::vector<T*>& result);
     
    protected:
      std::vector<Object *> m_Childs;
      std::string m_Name;
    };
     
     
    class Pomme : public Object
    {
     
    };
     
    class Poire : public Object
    {
     
    };
    Si j'ai un container de type Object, et que je veux retrouver ses enfants de type Poire se nommant "auchocolat" je rempli mon vecteur result en dynamic castant les enfant qui match.

    je ne vois pas trop comment faire d'autre, y a t il une methode ou un design evitant ces dynamic_cast ?

    merci d'avance pour vos reponses.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Ton exemple reste encore flou. Tu peux détailler ton problème ?

  3. #3
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Il faut que tu revois effectivement ton design.

    Le problème vient du fait que tu possèdes un seul conteneur d'objet vers des Object*.

    Il faut généralement passer par plusieurs conteneurs plus spécialisés, et posséder quelque chose de très générique à la racine. Tout ce qui est commun à tous tes objets, en somme. (comme une position, une vitesse, un sprite d'affichage, etc...). Tu as une Factory qui s'occupe de créer les objets et de les remettre à ta classe qui gèrera tous tes objets de manière uniforme. C'est ta factory qui connaitra les types réels (vu que c'est lui qui les créera) et qui les remettra à qui en a besoin, sous forme de pointeur.

    Une autre manière de faire la chose, et qui est probablement une meilleure solution si tu comptes avoir une large hiérarchie, est le système de composants. En gros, ton entité n'est qu'un conteneur de composants, et chaque composant est indépendant, ou pas. Ils peuvent communiquer avec les autres composants, etc... Lorsque tu manipules une entité, tu peux savoir quels composants il possède et décider de le traiter ou pas.

  4. #4
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Sinon il y a une solution pas terrible, mais simple et qui fonctionne, qui consiste à utiliser un identificateur pour le type des classes filles. Ça donnera quelque chose comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    enum ObjectType
    {
    	POMME_OT,
    	POIRE_OT
    };
     
    class Object
    {
    public:
    	virtual int Id() const = 0;
     
    	void Find( int id, std::vector<Object*>& result ) const
    	{
    		std::vector<Object*>().swap( result ); // je vide result, au cas où
    		for ( std::vector<Object *>::const_iterator it = m_Childs.begin(); it != m_Childs.end() ; ++it )
    			if ( (*it)->Id() == id )
    				result.push_back( *it );
    	}
     
    	void CreateChild( int id );
     
    protected:
    	std::vector<Object *> m_Childs;
    };
     
    class Pomme : public Object
    {
    public:
    	int Id() const { return POMME_OT; }
    };
     
    class Poire : public Object
    {
    public:
    	int Id() const { return POIRE_OT; }
    };
     
    void Object::CreateChild( int id )
    {
    	switch (id) {
    	case POMME_OT:
    		m_Childs.push_back( new Pomme() );
    		break;
    	case POIRE_OT:
    		m_Childs.push_back( new Poire() );
    		break;
    	default:
    		// problem!
    		std::cout << "error bla bla..." << std::endl;
    	}
    }
     
     
    int main()
    {
    	Pomme root;
    	root.CreateChild( POMME_OT );
    	root.CreateChild( POIRE_OT );
    	root.CreateChild( POMME_OT );
    	root.CreateChild( POMME_OT );
    	root.CreateChild( POIRE_OT );
     
    	std::vector<Object*> pommes;
    	root.Find( POMME_OT, pommes );
     
    	//...
    }
    le code ci-dessus compile et fonctionne, mais on voit bien que c'est pas terrible.

    Le plus propre est, comme souvent, de dédier: créer une classe Noeud qui contiendra un Object (ou un Object* selon ton design).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  5. #5
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Première impression à froid : C'est bien une architecture parent-enfant que tu veux là ? J'aurai plutot l'impression que c'est un pattern décorateur dont tu aurais besoin avec ton premier exemple.
    Dans le cas contraire, la solution classique est d'avoir une class Noeud (Node) qui va représenter un noeud de ton arbre et une abstraction de tes classes métiers. Ici ton Object fait les 2 à la fois, ce qui n'est pas terrible.

    Poukill.

  6. #6
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Un pattern "Visitor" me semblerait approprié, non ?

  7. #7
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Sinon, quelque chose de semblable à ce que je mets en place dans mon article, fortement basé sur le système de Qt : http://alp.developpez.com/tutoriels/type-erasure/#LIV

Discussions similaires

  1. [Evènement]Comment gérer ceux des CTRL enfants sans déclencher celui du CTRL parent ?
    Par Anto03 dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 29/09/2008, 13h57
  2. Réponses: 6
    Dernier message: 08/05/2006, 14h18
  3. [MDI] Atteindre le parent depuis l'enfant.
    Par rouche dans le forum C++Builder
    Réponses: 7
    Dernier message: 09/02/2006, 23h10
  4. [C#] [XML] Insérer un noeud entre un parent et ses enfants
    Par frechy dans le forum Windows Forms
    Réponses: 10
    Dernier message: 04/04/2005, 15h52
  5. [VB6] TreeView -- faire la différence entre le parent et l'enfant
    Par Baquardie dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 22/10/2004, 22h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo