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 :

Pattern strategy et inclusions réciproques


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 11
    Points : 15
    Points
    15
    Par défaut Pattern strategy et inclusions réciproques
    Bonjour,

    J'ai une classe A avec tout un tas d'attributs. Dans la classe A je créé un pointeur vers la classe B, la classe B a pour but d'effectuer un algorithme prenant en argument tous les attributs de A (design strategy ).

    Ma classe B possède une méthode qui prends en argument une référence constante sur un objet A.


    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <iostream>
     
    #include "b.h"
    #include "a.h"
     
    int main()
    {
            A a;
            a.sayHello();
            return 0;
    }
    a.h
    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
    #ifndef A_H
    #define A_H
     
    #include "b.h"
     
    class A
    {
    public:
            A():m_sMessage("Message cree dans le constructeur") { m_pB = new B; }
            const std::string& getMessage() const { return m_sMessage; }
            void sayHello() { m_pB->sayHello(*this); }
    private:
            B* m_pB;
            std::string m_sMessage;
    };
     
    #endif
    b.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #ifndef B_H
    #define B_H
     
    #include "a.h"
     
    #include <iostream>
     
    class B
    {
    public:
            void sayHello(const A& a) { std::cout << a.getMessage() << std::endl; }
    };
     
    #endif
    J'ai un problème d'inclusion des fichiers (j'imagine). Le compilateur me crache:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    In file included from b.h:4,
                     from main.cpp:3:
    a.h:13: error: ISO C++ forbids declaration of ‘B’ with no type
    a.h:13: error: expected ‘;’ before ‘*’ token
    a.h: In constructor ‘A::A()’:
    a.h:9: error: ‘m_pB’ was not declared in this scope
    a.h:9: error: expected type-specifier before ‘B’
    a.h:9: error: expected `;' before ‘B’
    a.h: In member function ‘void A::sayHello()’:
    a.h:11: error: ‘m_pB’ was not declared in this scope

    Que faire??

    Merci

  2. #2
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Bonjour,

    Réponse courte :
    Tu dois casser la dépendance cyclique (a.h a besoin de b.h qui a besoin de a.h…).
    Étant donné que la classe A n'a en tant que membre qu'un pointeur vers B, tu peux faire une déclaration anticipée de B à la place de l'inclusion de b.h dans a.h :
    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
     
    #ifndef A_H
    #define A_H
     
    class B; //déclaration anticipée
     
    class A
    {
    public:
            A();
            const std::string& getMessage() const;
            void sayHello();
    private:
            B* m_pB;
            std::string m_sMessage;
    };
     
    #endif
    Il faut par contre que les définitions de tes fonctions aillent dans un a.cpp, où tu devras inclure b.h.
    Plus d'infos : http://cpp.developpez.com/faq/cpp/in...erence_croisee


    Réponse complète :
    Ton implémentation du pattern Strategy est incorrecte.
    Les classes implémentant ton algorithme doivent implémenter une interface commune. La classe A doit avoir un pointeur vers objet du type de cette interface.
    En fait, avec une implémentation correcte de Strategy, tu ne devrais même pas avoir de problème de dépendance cyclique. A est dépendant de l'interface, les classes algorithme sont dépendantes de l'interface et de A, et c'est tout.
    Tu devrais relire plus attentivement la définition du pattern (en particulier les exemples donnés avec).
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 11
    Points : 15
    Points
    15
    Par défaut
    Merci pour ta réponse.

    En fait je viens de comprendre qu'il existe des cas où on ne peut pas inliner autant qu'on le voudrait, car on se retrouve avec des dépendances cycliques. Dans un cas de dépendances cycliques, il suffit de nettoyer ses headers pour n'avoir plus que des pointeurs et des références, et ainsi pouvoir utiliser des déclarations anticipées. C'est dommage mais c'est comme ça.

    Pour ce qui est de l'implémentation de mon pattern strategy, je crée des classes dérivées B1, B2, B3 etc... et je fais en sorte que B soit une classe virtuelle pure. Ensuite dans A je crée un pointeur vers un objet de type B. Seulement pour ne pas multiplier les headers, j'écris toutes les classes B,B1,B2,B3 dans le même fichiers .h c'est pourquoi je me suis retrouver avec des dépendances cycliques. Enfin je crois...

    Et donc ça ce n'est pas vraiment un pattern strategy?

  4. #4
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    En fait je viens de comprendre qu'il existe des cas où on ne peut pas inliner autant qu'on le voudrait, car on se retrouve avec des dépendances cycliques.
    En effet.
    Attention à ne pas tout inliner non plus. Les constructeurs et destructeurs, par exemple, sont très souvent de mauvais candidats à l'inlining, étant données toutes les instructions implicites qu'ils exécutent.

    Citation Envoyé par ThinkerR Voir le message
    Pour ce qui est de l'implémentation de mon pattern strategy, je crée des classes dérivées B1, B2, B3 etc... et je fais en sorte que B soit une classe virtuelle pure. Ensuite dans A je crée un pointeur vers un objet de type B. Seulement pour ne pas multiplier les headers, j'écris toutes les classes B,B1,B2,B3 dans le même fichiers .h c'est pourquoi je me suis retrouver avec des dépendances cycliques. Enfin je crois...
    C'est tout à fait ça, tu devrais créer un header pour chaque classe. Il n'y a aucun mal à multiplier les headers : non seulement c'est mieux organisé (ce n'est pas pour rien que Java l'impose), mais en plus ça réduit la taille des unités de compilation (1 unité de compilation = 1 fichier .cpp + tous les .h #includés), ce qui réduit le temps de compilation.

    Et donc ça ce n'est pas vraiment un pattern strategy?
    Si si, au temps pour moi, j'ai cru que B était une classe concrète et non une interface (== classe avec des fonctions membres virtuelles pures), ça roule de ce côté là
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Pattern Strategy et Constructeurs Virtuels VCL
    Par ShaiLeTroll dans le forum C++Builder
    Réponses: 4
    Dernier message: 24/12/2010, 15h48
  2. MVC et pattern Strategy
    Par polymorphisme dans le forum MVC
    Réponses: 6
    Dernier message: 31/12/2009, 14h58
  3. [Stratégie] Pattern Strategie avec parametres variables
    Par new.proger dans le forum Design Patterns
    Réponses: 3
    Dernier message: 10/06/2007, 20h48
  4. Réponses: 4
    Dernier message: 22/12/2004, 14h28

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