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 :

Problème de débutant pour l'agregation


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Problème de débutant pour l'agregation
    Bonjour, c'est la première fois que je post, alors je vais essayé d'être clair mais ça pas être facile.
    Voila en faite j'ai 5 classes A, B, C ,D ,E
    ref: UML.jpg en fichier joins
    A agreg B
    B agreg D ou E
    D et E dérive de C

    La classe B possède une méthode qui return un type C* (donc un objet D ou E si ma logique et bonne)
    Encore un petit truc je souhaite avoir la référence de la classe instanciatrice dans la classe instanciée. (j'ai déjà fais ça en JAVA et je n'avais pas eu de problème...)

    Bref voila l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    In file included from B.h:17,
                     from E.h:16,
                     from E.cpp:13:
    C.h:20: erreur: ISO C++ forbids declaration of «B» with no type
    C.h:20: erreur: expected «;» before «*» token
    comme si je n'avais pas déclaré B.h dans le fichier C.h ???
    J'ai beau mettre en commentaire le #include B.h dans C.h l'erreur ne change pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #if !defined(_A_H)
    #define _A_H
    class A {
    };
    #endif  //_A_H
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #if !defined(_B_H)
    #define _B_H
    #include "A.h"
    #include "C.h"
    class B {
    public:
    	A* PtrClassA;
    	B(A* PtrClassA);
    	C* Operation();         
    };
    #endif  //_B_H
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #if !defined(_C_H)
    #define _C_H
    #include "B.h"
    class C {
    public:
    	B* PtrClassB;                  // l'erreur est ici: il  connaît pas B ??? pourquoi?
    };
    #endif  //_C_H
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #if !defined(_D_H)
    #define _D_H
    #include "C.h"
    class D : public C {
    public:
    	D(B* PtrClassB);
    };
    #endif  //_D_H
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #if !defined(_E_H)
    #define _E_H
    #include "B.h"
    #include "C.h"
    class E : public C {
    public:
    	E(B* PtrClassB);
    };
    #endif  //_E_H
    Images attachées Images attachées  
    Fichiers attachés Fichiers attachés

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Il faut utiliser une déclaration anticipée.

    MAT.

  3. #3
    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
    Bonjour et bienvenu,
    C'est un problème classique d'inclusions circulaires. Cela se règle en utilisant la déclaration anticipée:
    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
     
    #if !defined(_B_H)
    #define _B_H
    // On dit au compilateur que A et C sont des classes :
    class A;
    class C;
    class B {
    public:
    	A* PtrClassA;
    	B(A* PtrClassA);
    	C* Operation();         
    };
    #endif  //_B_H
    C.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #if !defined(_C_H)
    #define _C_H
    class B;
    class C {
    public:
    	B* PtrClassB;
    };
    #endif  //_C_H
    etc...
    Ensuite, tu ne fais l'include du .h que dans le .cpp :
    B.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ...
    #include "B.h"
    #include "A.h"
    #include "C.h"
    etc...

    Tu trouveras ici quelques explications, et bien sûr la FAQ

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Il y a une erreur dans ton diagramme

    A moins que tu ne veuille que ta classe B aggrège un D ET un E (ce qui peut être possible, mais qui est en désaccord avec ton explication, l'aggrégation doit partir de B et aller à... C.

    Du fait que D et E dérivent de C, tu pourra donc au choix transmettre un pointeur vers un objet de type D ou vers un objet de type E

    Sois attentif toute fois au fait que, comme B ne connait l'objet que par l'intermédiaire de C, les seules fonctions que tu pourra appeler au travèrs de ce pointeur seront celles... qui sont définies dans C (si tu as, dans D ou dans E une fonction foo qui n'est pas déclarée dans C, le compilateur refusera une invocation proche de ptr->foo() )

    L'avantage, c'est que, lorsque tu défini ta classe B, tout ce qu'il te faut, c'est prévenir le compilateur qu'il existe une classe nommé C (il n'a même pas besoin de savoir que D et E qui en héritent existent )
    fichier B.hpp
    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
    /* le garde anti inclusion multiple */
    #ifndef B_HPP
    #define B_HPP
    class C; // ca suffit pour que le compilateur sache que la classe C existe
    class A; // ca suffit pour que le compilateur sache que la classe A existe
    class B
    {
        public:
            B(/*...*/);
            ~B();
            /* les fonctions sympa de B 
             * NOTA: il ne faut ni essayer de renvoyer une instance
             * de A ou de C (un pointeur ou une référence (constante
             * ou non) seront accepté(s) ), ni d'essayer d'accéder
             * au contenu de A ou de C dans le fichier d'en-tête
             */
        private:
            /* "retour" d'agrégation (bidirectionnelle) vers la classe A */
            A * prtA;
            /* aggrégation (bidirectionnelle) vers la classe C 
             * les classes D et E peuvent se faire passer pour la classe C
             */
            C * ptrC;
    };
    /* la fin du garde anti inclusion multiple */
    #endif // B_HPP
    Si tu te contente de renvoyer un pointeur ou une référence (constante ou non) vers un objet de la classe A ou de la classe C, tu peux t'en tenir là...

    Si, par contre, une fonction de B essaye d'accéder à une fonction membre de A ou de C, il faut que le compilateur connaisse le contenu de la classe en question au moment où il est fait appel à la fonction...

    Pour ce faire, il faut inclure l'en-tête respectif de la classe en question
    B.cpp
    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
    /* il nous faut la définition de B*/
    #include "B.hpp"
    /* ainsi que celle des classes A et C */
    #include "A.hpp"
    #include "C.hpp"
    /* une fonction de B qui essaye d'accéder au contenu de A
     * si l'inclusion de A.hpp n'était pas présente, le compilateur
     * la refuserait
     */
    void B::doSomethingWithA()
    {
        ptrA->laFonction();
    }
    /* une fonction de B qui essaye d'accéder au contenu de C
     * si l'inclusion de C.hpp n'était pas présente, le compilateur
     * la refuserait
     */
    void B::doSomethingWithC()
    {
        ptrC->bar();
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Remerciment
    Je remercie toutes les personnes qui ont répondu à mon topic à la fois pour leurs explications et leur rapidité. Je vais enfin pouvoir continuer à "GEEKer"

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

Discussions similaires

  1. problème de débutant pour tester un projet!
    Par yacinebenz dans le forum Android
    Réponses: 3
    Dernier message: 10/07/2013, 10h13
  2. problème de déclaration pour débutant !
    Par keviin dans le forum VB.NET
    Réponses: 2
    Dernier message: 05/02/2009, 23h11
  3. Réponses: 1
    Dernier message: 22/01/2009, 11h23
  4. Réponses: 4
    Dernier message: 10/09/2007, 19h23
  5. problème de syntaxe pour un débutant
    Par marsamandes dans le forum Langage
    Réponses: 3
    Dernier message: 02/05/2007, 13h25

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