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 :

[Débutant] Attribut d'une classe du type d'une autre classe


Sujet :

C++

  1. #1
    Membre averti
    Avatar de stc074
    Homme Profil pro
    Codeur du dimanche
    Inscrit en
    Janvier 2009
    Messages
    1 015
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Codeur du dimanche

    Informations forums :
    Inscription : Janvier 2009
    Messages : 1 015
    Points : 407
    Points
    407
    Billets dans le blog
    1
    Par défaut [Débutant] Attribut d'une classe du type d'une autre classe
    Bonjour, j'ai un peu de mal avec la POO c++ ça change du java.
    J'ai une classe Commande dans laquelle je désire avoir un attribut du type Connection (une autre classe) :

    Commande.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
    19
    20
    21
    22
    #ifndef COMMANDE_H_
    #define COMMANDE_H_
     
    #include "Global.h"
    #include "Connection.h"
     
    class Connection;
     
    class Commande : public Global {
     
    public:
    	Commande(std::string);
    	void init(void);
    	std::string getId(void);
    	Connection getConn(void);
     
    private:
    	std::string id;
    	Connection conn;
    };
     
    #endif /* COMMANDE_H_ */
    Connection conn est souligné en rouge(eclipse) avec comme erreur "field ‘conn’ has incomplete type"
    J'ai pas trouvé d'explication sur les attributs de type objet dans la déclaration de classe C++; la j'ai fait une déclaration "à la java" mais ça ne marche pas ;-).
    Merci pour votre aide.

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Points : 158
    Points
    158
    Par défaut
    Ta déclaration anticipée n'est pas nécessaire :
    , tu devrais la supprimer.

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Pas nécessaire ici, certes, mais pas néfaste non plus, a priori. Peux-tu nous montrer à quoi ressemble Connection.h ?

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 162
    Points
    17 162
    Par défaut
    Regarde aussi du côté des namespaces.

    Tu as peut-être un network::Connection, ou je ne sais quoi du même goût.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 127
    Points : 33 036
    Points
    33 036
    Billets dans le blog
    4
    Par défaut
    La forward declaration n'est pas utilisable ici, Connection est utilisé en objet statique et non comme pointeur/référence.

    Enfin, ça compile ? il ne faut pas faire confiance aveuglément à son IDE, à fortiori eclipse pour du C++ amha.

  6. #6
    Membre averti
    Avatar de stc074
    Homme Profil pro
    Codeur du dimanche
    Inscrit en
    Janvier 2009
    Messages
    1 015
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Codeur du dimanche

    Informations forums :
    Inscription : Janvier 2009
    Messages : 1 015
    Points : 407
    Points
    407
    Billets dans le blog
    1
    Par défaut
    Finalement j'ai trouvé mon erreur, à la base je voulais récupérer à l'initialisation de l'objet Connection l'objet Commande qui l'initialisait (donc en gros avoir un objet Connection dans Commande, et un objet Commande(this) dans Connexion) je faisais donc un include de "Commande.h" dans Connexion.h, après avoir supprimé cet include tout fonctionne.
    Par contre j'aimerais savoir si j'avais voulu continuer dans cette voie (faire passer a mon attribut Connection le this de l'objet qui l'a initialisé) comment aurais-je pu faire? sachant que je n'y suis pas parvenu.
    Merci.

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 136
    Points
    23 136
    Par défaut
    Quelque chose comme ça ?
    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
    class B;
     
    class A
    {
         A();
         B b;
    };
     
    A::A() : b(this)
    {
    }
     
    class B
    {
         B();
         A * ptrA;
    };
     
    B::B(A * ptr) : ptrA(ptr)
    {
     
    }

  8. #8
    Membre averti
    Avatar de stc074
    Homme Profil pro
    Codeur du dimanche
    Inscrit en
    Janvier 2009
    Messages
    1 015
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Codeur du dimanche

    Informations forums :
    Inscription : Janvier 2009
    Messages : 1 015
    Points : 407
    Points
    407
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Quelque chose comme ça ?
    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
    class B;
     
    class A
    {
         A();
         B b;
    };
     
    A::A() : b(this)
    {
    }
     
    class B
    {
         B();
         A * ptrA;
    };
     
    B::B(A * ptr) : ptrA(ptr)
    {
     
    }
    ben le but c'est ça oui mais je n'utilisais pas les pointeurs, par contre la declaration du constructeur de B n'est pas bonne non ?
    Merci.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 127
    Points : 33 036
    Points
    33 036
    Billets dans le blog
    4
    Par défaut
    Je ne pense pas que ça marche.

    Tu utilises une forward declaration pour B, alors que B est déclaré comme membre de A et B n'a pas de constructeur par défaut.
    A a donc besoin de connaître la définition complète de B.

    http://cpp.developpez.com/faq/cpp/?p...erence_croisee

  10. #10
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 136
    Points
    23 136
    Par défaut
    Autant pour moi, je savais que ça marchais pour les références et les pointeurs, mais je ne pensais pas que cela n'était pas valable pour les objets.

    On en apprend tous les jours^^

    Voici le code corrigé
    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
    class A;
     
    class B
    {
        public :
         B(A *);
         A * ptrA;
    };
     
    class A
    {
        public :
         A();
         B b;
    };
     
    A::A() : b(this)
    {
    }
     
    B::B(A * ptr) : ptrA(ptr)
    {
     
    }

  11. #11
    Membre averti
    Avatar de stc074
    Homme Profil pro
    Codeur du dimanche
    Inscrit en
    Janvier 2009
    Messages
    1 015
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Codeur du dimanche

    Informations forums :
    Inscription : Janvier 2009
    Messages : 1 015
    Points : 407
    Points
    407
    Billets dans le blog
    1
    Par défaut
    Merci pour vos réponse j'avance peu à peu,
    J'ai fait des déclarations et initialisation sur le même modèle que A et B mais j'ai un probleme dans Commande.h (A donc) :
    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
    #ifndef COMMANDE_H_
    #define COMMANDE_H_
     
    #include "Global.h"
    #include "Connection.h"
     
    class Connection;
     
    class Commande : public Global {
     
    public:
    	Commande(std::string);
    	void init(void);
    	std::string getId(void);
    	Connection getConn(void);
     
    private:
    	std::string id;
    	Connection conn;
    };
     
     
     
    #endif /* COMMANDE_H_ */
    Connection conn est souligné en rouge : field ‘conn’ has incomplete type
    Je ne peux pas lancer on programme.
    Merci.

  12. #12
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 136
    Points
    23 136
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Commande(const std::string &);
    const std::string & getId(void);
    const Connection & getConn(void);
    Évitons au maximum les copies inutiles.

    Sinon pour ton message d'erreur, regarde la dernière réponse de Bousk.

  13. #13
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    La première question à se poser est : "pour définir Commande, est-ce que j'ai besoin de la définition de connection, ou est-ce qu'une déclaration suffit ?" (définition = class Connection {/*...*/ }; et déclaration = class Connection;)

    Qu'est-ce qui pourrait nécessiter la définition de Connection ? Si Commande dérive de Connection, ou possède une variable membre de type Connection (une variable de type pointeur sur Connection ou référence à Connection ne gêne pas, et il y a des cas plus subtils, mais pour l'instant passons dessus), la définition est nécessaire. Sinon, une déclaration suffit.

    Si on a besoin d'une définition, pas le choix, on a besoin de toute la définition, et le moyen le plus simple (et le seul qui tienne la route en pratique) consiste à inclure Connection.h. Sinon, il suffit d'écrire la déclaration (class Connection;).

    Même question à se poser pour l'utilisation de Commande dans Connection.

    Maintenant, que se passe-t-il si tu décides que dans les deux cas, tu as besoin d'inclure le fichier d'en-tête (c'est à dire que tu as besoin de la définition) ? Il ne faut pas oublier que le mécanisme d'include est très rudimentaire et purement textuel. Prenons un fichier toto.cpp qui inclurait commande.h. Ce faisant, les include guards laissent l'inclusion se faire, mais COMMANDE_H_ est désormais défini. Commande.h va alors inclure connection.h, les include guards vont laisser passer, et CONNECTION_H_ va désormais être défini. connection.h va alors inclure, à nouveau, commande.h, et cette fois-ci, les include guards vont faire que rien ne va être inclus.

    Donc, bien que connection.h inclue commande.h, dans cet exemple, quand on va arriver à la définition de Connection, on n'aura pas au préalable la définition de Commande, et donc, on aura le genre d'erreurs que tu rencontres. Les include guards auront empêché de partir en boucle infinie dans les #include, mais au prix d'avoir coupé à un endroit qui pose problème. Comment résoudre ça ?

    Et bien, il n'y a en fait pas de vrai problème, parce que si tu as besoin d'inclure le fichier d'en-tête dans les deux cas, c'est que tu as fait une mauvaise décision. Car si Connection a besoin de commande.h et Commande a besoin de connection.h, c'est qu'il y a utilisation circulaire des objects (et là je ne parle plus simplement de circularité dans les .h, mais d'un objet qui contient un autre qui contient le premier...). N'oublie pas que contrairement à Java, si tu veux un pointeur en C++, tu dois le demander explicitement. Si un objet en contient un autre, il le contient vraiment. Et autant des références/pointeurs circulaires entre objets ne pose aucun problème, autant un objet A qui contient un B qui contient un A... serait un objet de taille infinie.

    Donc, pour résumer : Tu dois dans ton analyse "est-ce que j'ai besoin de la définition, ou est-ce que la déclaration suffit?" avoir au moins une fois où la déclaration suffit. Cette fois là, tu évites d'inclure, tu déclares juste. Du coup, plus d'inclusion circulaire, avec les problèmes qu'une telle inclusion causerait (même avec les include guards).




    PS : commande est en français, connection en anglais, ça ne facilite pas la lecture du code.

  14. #14
    Membre averti
    Avatar de stc074
    Homme Profil pro
    Codeur du dimanche
    Inscrit en
    Janvier 2009
    Messages
    1 015
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Codeur du dimanche

    Informations forums :
    Inscription : Janvier 2009
    Messages : 1 015
    Points : 407
    Points
    407
    Billets dans le blog
    1
    Par défaut
    Merci JolyLoic pour ces précisions, je vais repenser mon programme.

Discussions similaires

  1. [Modèle Relationnel] Faire une table par type ou une table des types ?
    Par jax54000 dans le forum Schéma
    Réponses: 12
    Dernier message: 18/11/2009, 11h43
  2. Attribut d'une classe du type d'une autre classe
    Par Ragnarok666 dans le forum Débuter
    Réponses: 12
    Dernier message: 14/04/2009, 17h43
  3. [Free Pascal] [2.2] Impossible d'assigner une variable de type T à une variable de type T
    Par Hibou57 dans le forum Free Pascal
    Réponses: 3
    Dernier message: 12/10/2007, 12h31
  4. Tester le type d'une variable de type "Variant"
    Par nono27200 dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 30/08/2007, 21h26
  5. Réponses: 2
    Dernier message: 10/04/2007, 12h39

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