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éfinition de 2 classes possédant chacune des Ptr vers des objets de l'autre


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 6
    Points
    6
    Par défaut Définition de 2 classes possédant chacune des Ptr vers des objets de l'autre
    Bonjour,

    Le titre n'est pas très représentatif mais je ne sais pas comment le dire...

    Contexte :

    Je développe une application utilisant un maillage (algo de DELAUNAY) et je cré plusieurs objet dont "Triangle" et "Segment". Pour mettre en place cet algo j'ai besoin que ma classe Triangle possède 3 pointeurs vers des objets type Segment (logique un triangle à bien 3 arêtes) donc la pas de Pb mais j'ai également besoin que ma classe Segment possède 2 pointeurs vers des objets type Triangle (les 2 triangles juxtaposés du maillage partageant le segment en question.)

    J'ai donc voulu déclarer mes classes comme cela :

    Pour la classe Triangle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef TRIANGLE
    #define TRIANGLE
     
    #include <Segment.h>
     
    class Triangle
    {
     
        public :
     
            Segment *S1, *S3, *S3;
    };
    #endif
    Pour la classe Segment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef SEGMENT
    #define SEGMENT
     
    #include <Triangle.h>
     
    class Segment
    {
     
        public :
     
            Triangle *Tv1, *Tv2;
    };
    #endif
    Le Hic c'est que ca plante à la compilation sur la ligne 11 de la classe Triangle : 'Segment' does not name a type'.

    => Si je comprend bien c'est qu'il ne connait pas le type 'Segment' à ce moment là alors qu'il est bien défini en include.

    Si je supprime #include <Triangle.h> de la classe Segment, le problème disparait mais je ne peux alors plus avoir de pointeurs vers des triangles dans cette classe ce qui est problématique.

    Je sens bien que ca ne peut pas marcher comme cela puisque chaque classe a besoin de l'autre pour être définie mais comment solutionner proprement ce problème ?

    Merci d'avance pour votre aide, et désolé si la réponse est obvious, je débute en programmation.

    Bien cordialement,

    Nico

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Il faut utiliser une forward declaration dans les header.
    En fait il faut toujours préférer les forward declaration dans les header et favoriser les include dans les fichiers sources.
    http://cpp.developpez.com/faq/cpp/?p...-une-a-l-autre
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Merci Bousk pour ta réponse.

    J'ai consulté le lien dans la FAQ qui explique ce qu'est la déclaration anticipée. J'ai modifié ma classe Segment ainsi :
    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 SEGMENT
    #define SEGMENT
     
    #include <Triangle.h> :  // Ligne supprimée
    
    Class Triangle;
     
    class Segment
    {
     
        public :
     
            Triangle *Tv1, *Tv2;
    };
    Cela compile sans problème.

    Par contre peux tu me détailler ce que tu veux dire par :
    En fait il faut toujours préférer les forward declaration dans les header et favoriser les include dans les fichiers sources.
    Car au final je déclare toujours mes classes dans un header (un par classe) et y ajoute en tête tous les includes nécessaires au fonctionnement de la classe. Exemple concret :
    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 TRIANGLE
    #define TRIANGLE
     
    #include <QPoint>
    #include <QVector>
     
    #include <cmath>
    #include <C_Mesh/Segment.h>
     
    #include <C_Generique/Maths.h>
     
    class Triangle
    {
     
        //
    }
    #endif
    Comment devrais je appliquer ce principe ici par exemple ? le pourrais je ?

    Merci encore pour ton intervention

  4. #4
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut
    Bonjour.

    La forward declaration ne fonctionne qu'avec des pointeurs, si tu déclares :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Foo{
        Objet obj;
    };
    , tu seras obligé d'inclure la déclaration d'Objet (#include<objet.h> //ou autre.

    Si tu utilises exclusivement des pointeurs d'Objet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Foo{
        Objet *obj;
    };
    , tu peux sans problème écrire class Objet; avant de déclarer class Foo {}.
    En revanche l'include sera déplacé dans la définition de Foo, dans le fichier cpp.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Merci Daïmanu pour ta réponse, je crois que je comprend bien la déclaration anticipée.

    Est ce obligatoire de placer le #include <Objet.h> dans le fichier Foo.cpp ou pourrait on créer un fichier GenericInclude.h qui contiendrait tous les includes nécessaires à toutes les classes du projet ? L'avantage serait de ne les spécifier qu'une seule fois ...

  6. #6
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut
    Tu peux créer un gros fichier d'include.

    L'inconvénient est que ça va allonger la compilation, vu que chaque fichier cpp va recevoir tout le contenu de tous les fichiers inclus.
    De plus, il risque d'y avoir des problèmes de collision si les fichiers définissent des macros / classes / variables avec le même nom.

    Généralement on recommande de n'inclure uniquement ce dont on a besoin.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Ah ok car meme si je cré un gros fichier d'include, il faudra que je le mette en entete de chaque fichier .cpp ? Dans ce cas c'est clair ca vaut pas le coup. je pensais ne l'inclure que dans le main par exemple...

    Autrement je viens de tester un exemple ou j'ai fait :
    - une déclaration anticipée d'une classe A dans une classe B
    - alors que B contient des pointeurs vers A ET des objets de type A
    - sans ajouter #include <A> dans le fichier B.cpp

    => Ca a compiler parfaitement... Est ce que cela est normal ? Pourrait s'expliquer par le fait que #include <A> est présent dans d'autres fichiers que B.cpp ?

  8. #8
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut
    Citation Envoyé par nicosmile_700 Voir le message
    Ah ok car meme si je cré un gros fichier d'include, il faudra que je le mette en entete de chaque fichier .cpp ?
    C'est recommandé (mais pas obligatoire).

    Citation Envoyé par nicosmile_700 Voir le message
    Ca a compiler parfaitement... Est ce que cela est normal ?
    Ça arrive souvent qu'on est pas rigoureux avec les includes.
    Prenons un exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Mot {
        std::string m_mot;
    };
    Ça ne compilera pas, puisque Mot ne sait pas ce qu'est un std::string.

    Par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //fichier quelconque cpp
    #include <string>
    #include "mot.h"
    fera que ça compile, car le string a été inclus avant le mot.
    Voila un article qui parle de ce sujet.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  9. #9
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par nicosmile_700 Voir le message
    ...
    Ca veut juste dire ce qui est écrit : préférer des forward declaration aux includes dans les headers.
    Quand à ton exemple, vu que tu coupes le corps de la classe, on pourra difficilement te dire autre chose que "peut-être".

    Citation Envoyé par Daïmanu Voir le message
    La forward declaration ne fonctionne qu'avec des pointeurs
    Et les références.

    Citation Envoyé par nicosmile_700 Voir le message
    Est ce obligatoire de placer le #include <Objet.h> dans le fichier Foo.cpp
    Si tu manipules un objet contenu dans Objet.hpp alors oui.

    Citation Envoyé par nicosmile_700 Voir le message
    ou pourrait on créer un fichier GenericInclude.h qui contiendrait tous les includes nécessaires à toutes les classes du projet ? L'avantage serait de ne les spécifier qu'une seule fois ...
    - toutes les classes n'ont pas besoin de tous les includes
    - on essaye de limiter les dépendances en général
    - si t'as envie de passer plus de temps à compiler qu'à programmer tu peux t'y risquer
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 222
    Points : 766
    Points
    766
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Il faut utiliser une forward declaration dans les header.
    En fait il faut toujours préférer les forward declaration dans les header et favoriser les include dans les fichiers sources.
    http://cpp.developpez.com/faq/cpp/?p...-une-a-l-autre
    Je suis d'accord mais il faut préciser que ce n'est possible qu'à condition d'utiliser des pointeurs ou des références vers les objets ces ces classes, pas directement des instances. Ce qui est d'ailleurs aussi une bonne pratique.

  11. #11
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par olreak Voir le message
    Je suis d'accord mais il faut préciser que ce n'est possible qu'à condition d'utiliser des pointeurs ou des références vers les objets ces ces classes, pas directement des instances. Ce qui est d'ailleurs aussi une bonne pratique.
    Conceptuellement si tu arrives à avoir une classe A composée d'une classe B elle-même composée d'une classe A
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    class A { B b; };
    class B { A a; };
    C'est même plus du wtf là, c'est carrément de la folie. Tu te retrouves avec A qui contient un B qui contient un A, qui.....
    Je préfère pas penser que quelqu'un puisse l'imaginer.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Merci à tous pour vos réponses, je pense avoir bien saisi la bonne facon de faire. Ne reste plus qu'à l'appliquer en reprenant le code déjà écrit !

    Encore merci

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/09/2011, 12h53
  2. Réponses: 5
    Dernier message: 04/05/2009, 14h54
  3. Réponses: 3
    Dernier message: 13/09/2007, 18h11
  4. [ETAT]Créer des liens vers des entetes de groupes
    Par tonyice80 dans le forum IHM
    Réponses: 7
    Dernier message: 06/04/2007, 23h37
  5. Réponses: 3
    Dernier message: 23/01/2007, 08h14

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