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 :

Classe A qui contient B et vice versa : Impossible ?


Sujet :

C++

  1. #1
    Membre régulier
    Inscrit en
    Mars 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : Mars 2010
    Messages : 74
    Points : 81
    Points
    81
    Par défaut Classe A qui contient B et vice versa : Impossible ?
    Salut !

    En souhaitant réaliser un Sudoku je suis tombé sur une erreur que je n'arrivais pas à comprendre.
    J'ai tout de même réussi à localiser où se trouve le souci et je l'ai extrait du projet pour essayer de le résoudre plus facilement.

    Voilà comment je peux illuster le souci. J'essaie de faire ceci :

    Soit une classe A qui a pour attribut un pointeur sur une instance de la classe B.
    Soit une classe B qui a pour attribut un pointeur sur une instance de la classe A.

    Ce qui donne les fichiers suivant : A.h, A.cpp, B.h et B.cpp
    Et voilà leur contenu :

    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
    // FICHIER A.h
    #ifndef A_H
    #define A_H
     
    #include "B.h"
     
    class A
    {
    	private:
    		B* m_b;
     
    	public:
    		A();
    };
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Fichier A.cpp
    #include <iostream>
     
    using namespace std;
     
    #include "A.h"
     
    A::A() : m_b(NULL)
    {
     
    }
    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
    // Fichier B.h
    #ifndef B_H
    #define B_H
     
    #include "A.h"
     
    class B
    {
    	private:
    		A* m_a;
     
    	public:
    		B();
    };
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Fichier B.cpp
    #include <iostream>
     
    using namespace std;
     
    #include "B.h"
     
    B::B() : m_a(NULL)
    {
     
    }
    Voilà les erreurs obtenues lors des compilations :
    g++ -Wall -c A.cpp
    In file included from A.h:4:0,
    from A.cpp:5:
    B.h:9:3: error: ‘A’ does not name a type
    g++ -Wall -c B.cpp
    In file included from B.h:4:0,
    from B.cpp:5:
    A.h:9:3: error: ‘B’ does not name a type
    Pourriez vous m'expliquer pourquoi cela plante ?
    Merci davance.
    SmallFitz.

  2. #2
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut
    Je pense que ca doit etre ca:
    Quand ta classe A cherche la classe B, elle n'est pas encore définit.
    j'ai eu ce problème une fois, j'ai du ordonner l'ordre de mes fichiers inclus dans mon projet pour que ca marche.

    Peut etre que ton idée marcherait avec un template ?

  3. #3
    Membre habitué Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Points : 154
    Points
    154
    Par défaut
    Peut-être qu'une simple déclaration de la classe B avant la définition de l'interface de ta classe A règlerait le problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class B;
    class A{
    ...
    };

  4. #4
    Membre régulier
    Inscrit en
    Mars 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : Mars 2010
    Messages : 74
    Points : 81
    Points
    81
    Par défaut
    Merci à vous deux !

    @DakM :
    J'ai essayé mais je n'ai pas trouvé une manière de changer l'ordre.
    Je ne connais pas encore les templates ! Quelle nouveauté auraient ils pu apporter ?

    @Xtrem_Voyageur :
    Joli ! J'ai essayé et ça fonctionne niquel.
    Quand on y réfléchit bien c'est tellement logique !
    Je n'avais jamais vu une simple déclaration dans une interface... C'est beau !

  5. #5
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par SmallFitz Voir le message
    Merci à vous deux !

    @DakM :
    J'ai essayé mais je n'ai pas trouvé une manière de changer l'ordre.
    Je ne connais pas encore les templates ! Quelle nouveauté auraient ils pu apporter ?

    @Xtrem_Voyageur :
    Joli ! J'ai essayé et ça fonctionne niquel.
    Quand on y réfléchit bien c'est tellement logique !
    Je n'avais jamais vu une simple déclaration dans une interface... C'est beau !
    C'est certes beau, syntaxiquement valide et tout et tout. Par contre, ça dénote avant tout d'un problème de conception si le but est de régler un soucis de dépendance circulaire.

    La relation "A utilise B utilise A" (de manière directe ou indirecte) va te poser des problèmes. Est-ce que tu es sûr que tu n'as pas d'autres solution ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Ben quand tu as une relation symétrique du genre :

    "H est marié à F qui est mariée à H",

    il n'y a pas grand chose d'autre à faire.

    Bon, certains diront que la mariage n'est pas une relation symétrique...

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par oodini Voir le message
    Ben quand tu as une relation symétrique du genre :

    "H est marié à F qui est mariée à H",

    il n'y a pas grand chose d'autre à faire.

    Bon, certains diront que la mariage n'est pas une relation symétrique...


    Ce genre de relation symétrique est rare, et dans chaque cas où on s'y trouve confronté il faut se demander pourquoi elle existe, qu'est-ce qu'elle apporte (au niveau design, pas au niveau code), et que devrait-on faire si elle n'existait pas.

    La plupart du temps, ça sent la loi de Demeter mal (voire non) utilisée à plein nez
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    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
    Pour la syntaxe : F.A.Q. Comment créer 2 classes qui font référence l'une à l'autre ?

    Pour le design, voir la réponse d'Emmanuel : cette référence croisée est-elle vraiment pertinente ?

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Ce genre de relation symétrique est rare, et dans chaque cas où on s'y trouve confronté il faut se demander pourquoi elle existe, qu'est-ce qu'elle apporte
    Que de questionnements qui surgissent quand vole la vaisselle.

  10. #10
    Membre régulier
    Inscrit en
    Mars 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : Mars 2010
    Messages : 74
    Points : 81
    Points
    81
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    C'est certes beau, syntaxiquement valide et tout et tout. Par contre, ça dénote avant tout d'un problème de conception si le but est de régler un soucis de dépendance circulaire.

    La relation "A utilise B utilise A" (de manière directe ou indirecte) va te poser des problèmes. Est-ce que tu es sûr que tu n'as pas d'autres solution ?
    Je crois que je pourrais m'en passer mais j'ai l'impression que l'utilisation des classes sera plus facile si je ne m'en passe pas.

    Pour la syntaxe : F.A.Q. Comment créer 2 classes qui font référence l'une à l'autre ?

    Pour le design, voir la réponse d'Emmanuel : cette référence croisée est-elle vraiment pertinente ?
    Merci pour la FAQ.
    J'ignore si elle est pertinente, je suis débutant et je n'ai jamais étudié de près les architectures de classe.

    Je vais essayer de présenter ce que je suis en train de réaliser.

    Je souhaite représenter en C++ un Sudoku.
    Voilà mon analyse : Un Sudoku contient des cases, des lignes horizontales et verticales, et des carrés.
    J'ai donc créé les classes suivantes (j'ai allégé le code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Sudoku
    {
    	private:
    		Case* m_cases; // tableau de 81 cases
    		Ligne* m_lignesH; // tableau de 9 lignes horizontales
    		Ligne* m_lignesV; // 9 lignes verticales
    		Carre* m_carres; // 9 carrés
    };
    Un carré a un index qui le différencie des autres carrés (position différente) et est composé d'un tableau de 9 pointeurs sur des cases, et il connait le Sudoku à qui il appartient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Carre
    {
    	private:
    		unsigned int m_index;
    		Case** m_cases;
    		Sudoku* m_sudoku;
    };
    Une ligne a un index qui la différencie des autres lignes (position différente), et est un tableau de 9 pointeurs sur des cases, et elle connait le Sudoku à qui elle appartient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Ligne
    {
    	private:
    		unsigned int m_index;
    		Case** m_cases;
    		Sudoku* m_sudoku;
    };
    Une case a un index qui la différencie des autres cases (position différente), une valeur (1à9), peut être cachée ou non, et elle sait à qui elle appartient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Case
    {
    	private:
    		unsigned int m_index;
    		unsigned int m_valeur;
    		bool m_cachee;
    		Carre* m_carre;
    		Ligne* m_ligneH;
    		Ligne* m_ligneV;
    		Sudoku* m_sudoku;
    };
    Comme on peut le constater Case est utilisée dans chacune des classes et je crois que je ne peux pas l'éviter.

    Chaque classe sait dans quelle autre classe elle est incluse. Ca je sais pas encore si c'est indispensable mais j'ai le sentiment que j'en aurais besoin plus tard, dans les constructeurs de copie par exemple, et puis avec ça j'ai l'impression que je ferais pas des instructions à ralonge, tout est accessible depuis n'importe quelle classe (avec les getteurs et setteurs adaptés bien sûr).

    Suis je à côté de la plaque ?

  11. #11
    Membre habitué Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Points : 154
    Points
    154
    Par défaut
    Je ne sais pas quelle utilisation tu comptes en faire, mais mon avis est que tu utilises l'orienté objet à l'extrême.
    Je n'aurais pour ma part pas été aussi loin dans les classes pour un simple sudoku.
    Je me serai bien passé de Case, Ligne, Colonne.
    Pourquoi compliquer ton sudoku lorsque les relations pour identifier une ligne ou une colonne sont simples.

    Quelle type d'opérations souhaites tu effectuer sur ces objets? une fonction qui vérifierait la validité? Moi je choisirai la simplicité dans ce cas-ci.

    En revanche tu peux garder ta classe Carré même si on peut s'en passer.

    Ce n'est que mon avis :-)

  12. #12
    Membre régulier
    Inscrit en
    Mars 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : Mars 2010
    Messages : 74
    Points : 81
    Points
    81
    Par défaut
    Je ne sais pas quelle utilisation tu comptes en faire, mais mon avis est que tu utilises l'orienté objet à l'extrême.
    Je n'aurais pour ma part pas été aussi loin dans les classes pour un simple sudoku.
    Je me serai bien passé de Case, Ligne, Colonne.
    Pourquoi compliquer ton sudoku lorsque les relations pour identifier une ligne ou une colonne sont simples.

    Quelle type d'opérations souhaites tu effectuer sur ces objets? une fonction qui vérifierait la validité? Moi je choisirai la simplicité dans ce cas-ci.

    En revanche tu peux garder ta classe Carré même si on peut s'en passer.

    Ce n'est que mon avis :-)
    Merci pour ton avis !

    Je considere ce Sudoku comme un vrai projet.
    Oui il y a peut être une maniere de le faire sans objet, ou en un seul, mais ce n'est pas comme ça qu'on m'a appris à appréhender un probleme.
    En utilisant les objets je trouve que c'est très structuré, très clair.
    Sans, ça va me faire un pâté de code aux multiples algo imbriqués... Incompréhensibles.
    En tout cas c'est ce que je me dis.

    Je ne sais pas encore ce que je vais faire précisemment avec ces objets, je n'ai justement pas attaqué l'algo
    Ce qui est sûr c'est que dans un premier temps je souhaite construire la base du Sudoku, sa grille et tout.
    Ensuite je vais mettre au point un systeme d'auto-résolution (en me calquant sur les grilles des jeux de sudoku)
    Après j'aimerais créer de toute pièce des sudokus "remplis".
    Puis j'essairais de créer des Sudoku comme dans les jeux : avec seulement quelques chiffres pour départ.
    C'est pour ça qu'au plus mes objets seront maniables et bien reliés entre eux, plus se sera l'extase (hum) lorsque j'aurais à me préocuper de l'algo.

    Enfin bref, ce qui me préoccupe c'est si les compositions que je mets de partout (A utilise B qui utilse A) sont une bonne maniere de faire, ou non. ^^

    EDIT : Je me dit aussi que plus sera décomposé mon projet, plus il sera facile d'y coller une interface graphique (chose que je ne sais absolument pas faire pour l'instant, mais ça serait cool de finir par ça).

  13. #13
    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,
    Il n'y a pas trop ou trop peu d'objet. La seule question à se poser est : à quoi servent ces différentes classes ? Quelles sont leur responsabilité ? A quoi sert le lien établie entre les classes ?

    Je pense qu'il y a une redondance évidente dans la classe Soduku entre les 81 cases, les lignes, les colonnes, les carrés. Au mieux, seules les 81 cases sont nécessaires. Ensuite, au besoin, avoir un itérateur sur les lignes, les colonnes ou les carrées de cases.

    Je ne pense pas que Case aie réellement besoin de connaître Soduku.

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

Discussions similaires

  1. éxecuter une classe qui contient une classe annonyme
    Par star-watcher dans le forum Débuter avec Java
    Réponses: 9
    Dernier message: 09/03/2009, 01h26
  2. Executer un jar qui contient plusieurs classes avec main
    Par touns390 dans le forum Débuter avec Java
    Réponses: 5
    Dernier message: 21/11/2008, 15h51
  3. Classe qui contient le main
    Par thierryler dans le forum Maven
    Réponses: 1
    Dernier message: 28/02/2008, 16h58
  4. Réponses: 1
    Dernier message: 28/12/2007, 12h14
  5. Bouton1 qui masque Bouton2 et vice versa
    Par Ercohuma59 dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 10/09/2007, 15h45

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