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 :

C++ , relations entre classes


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 371
    Par défaut C++ , relations entre classes
    Bonjour voila ,

    On a un projet a faire ... nous avons bloqué sur quelque chose , " l'agrégation " entre le main ( ) et une autre classe ...

    "L'autre classe" appellée A est celle qui a instancier l'objet de la classe B

    .h de A

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class A
    {
         B *ObjetDeB;
    };
    .h de B

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class B
    {
         public :
                     void loooool ( ) ;
    };

    dans le cpp de A

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    A::A()  // Constructeur
    {
        ObjetDeB = new B ; 
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    B A :: getmonB()    // getter de l'attribut
    {
        return *ObjetDeB ;
    }

    main () :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
       A MonA ;
       B *MonB ;
     
       *MonB = MonA.getmonB() ;
         MonB->loooool();
     
      return 0 ;
    }

    Pouvez me dire , si ce qui est au dessus est correct ? Merci davance

    En fait , ce que nous recherchons a faire , cest de pouvoir utiliser l'instance de B crée par A via son adresse dans le main ( )


    Cordialement

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Déjà au niveau des types, ce n'est pas bon. Tu retournes une copie du B interne et tu le mets dans un B*, ça ne peut pas fonctionner...

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 371
    Par défaut
    Ca ne peut pas fonctionner , pourtant ca fonctionne ...
    Que faire alors ?

  4. #4
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Retourner le pointeur directement (B*), et non un B, et ça marchera.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 371
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    B A :: getmonB()    // getter de l'attribut
    {
        return *ObjetDeB ;
    }

    je retourne pas le pointeur directement là ?

  6. #6
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Ben non, tu retournes une nouvelle instance de B par valeur, c'est juste une copie de l'objet pointé par ObjetDeB.

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Par défaut
    Citation Envoyé par Pugebad Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    B A :: getmonB()    // getter de l'attribut
    {
        return *ObjetDeB ;
    }
    je retourne pas le pointeur directement là ?
    non, tu renvoies une copie B.

    si tu veux renvoyer ton pointeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    B* A::getmonB()
    {
        return ObjetDeb;
    }
     
    int main()
    {
        //...
        MonB = MonA.getmonB();
    }

    MAIS

    si A crée l'objet B dans son constructeur et le détruit dans son destructeur ( à ne pas oublier... ), pourquoi en faire un pointeur?

    tu peux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class A
    {
        B ObjetDeB;
    };
    ( construction et destruction automatique, tu n'as pas à faire de new ou de delete )

    et renvoyer une référence (&) sur ton objet ( pas un pointeur ):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    B & getMonB()
    {
        return ObjetDeB;
    }
    et l'utiliser comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int main()
    {
        monA.getMonB().looool();
     
        // ou alors:
     
        B & monB = monA.getMonB();
        monB.looool();
     
        return 0;
    }
    En C++ le concept de références est important ( plus que celui de pointeur pour débuter ) .

    Effectivement, quand on a pas encore bien compris les pointeurs et qu'on rajoute par dessus les références, je conçois bien ça ne doit pas être clair du tout ce que je raconte.

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par Pugebad Voir le message
    Ca ne peut pas fonctionner , pourtant ca fonctionne ...
    Que faire alors ?
    Commencer par apprendre le B-A-BA de l'usage des pointeurs avant d'essayer d'écrire des programmes avec des pointeurs.

    Ne pas compiler avant d'avoir compris.

    Tester son programme pour vérifier qu'on a compris.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 60
    Par défaut
    Et il est preferable d'utiliser assez rapidement les auto_ptr et les shared_ptr qui permettent d'allegerla gestion de l'allocation dynamique de memoire

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    On pourrait répondre à toutes tes questions de la manière suivante:
    De manière générale, il faut préférer la gestion "statique" (AKA sur la pile) de la mémoire d'un objet plutôt que sa gestion "dynamique" (AKA sur le tas).

    Cela sous entend que, tant que tu peux faire autrement, tu ne devrais pas avoir recours aux pointeurs.

    Le corollaire de cela est que tu devrais utiliser éventuellement les conteneurs de la STL si tu envisage de "regrouper" plusieurs membres d'un même type.

    Les méthodes renvoyant un membre renvoyant alors une référence sur le membre en question (constante, ou non, en fonction des besoins)

    Les exception à ces règles sont relativement simples:
    1. Si un membre d'une de tes classes doit survivre à la destruction de l'objet qui le contient
    2. Si le membre représente en réalité le "conteneur" alors que la classe représente le "contenu" (exemple: un membre Usine dans une classe Travailleur)
    3. Si le membre est du même type (ou d'une classe de base/dérivée) que la classe (exemple: un membre de type Noeud dans la classe... Noeud)
    4. Si tu dois pouvoir profiter du polymorphisme, avec les méthodes virtuelles et autres astuces
    5. Si un membre peut ne pas exister (à ne pas confondre avec "peut ne pas être initialisé), et que tu veux pouvoir en tester l'existence

    alors, tu devra faire appel aux pointeurs, et vraisemblablement à l'allocation dynamique.

    Les méthodes renvoyant ces membres renvoyant alors un pointeur vers ces membres (constant ou non selon les besoins)

    A noter que, pour le premier cas, il peut s'avérer utile d'avoir une classe séparée dont la responsabilité sera, justement, de gérer les éléments alloués dynamiquement, et que dans le deuxième cas, le pointeur peut pointer vers un élément créé de manière "statique".
    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

  11. #11
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut shared_ptr, allocations dynamiques et pédagogie
    Disclaimer: Ami débutant en C++, tous les exemples de code de ce message sont faux, archi-faux. Ne viens pas me dire que tu n'étais pas prévenu.

    Citation Envoyé par bdeuu Voir le message
    Et il est préférable d'utiliser assez rapidement les auto_ptr et les shared_ptr qui permettent d'alléger la gestion de l'allocation dynamique de mémoire
    Oui, mais pas trop vite : j'ai observé (ici) que certains commencent à utiliser shared_ptr avant d'avoir compris ce qu'est l'allocation dynamique, d'où des horreurs du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    shared_ptr<A> p;
    A a;
    p.reset (&a);
    Le problème, AMA, est que shared_ptr est présenté comme la baguette magique qui fait qu'on n'a plus à s'embêter à comprendre l'allocation dynamique, et comme un GC intégré au langage (comme si avec les smart pointers C++ devenait Java); alors qu'au contraire, je ne vois pas comment on peut comprendre shared_ptr sans comprendre l'usage correct de delete.

    Le discours : "laisser les shared_ptr gérer les désallocations tous seuls" peut, mal interprété, devenir "je n'ai plus à besoin de comprendre comment ça marche", et conduire à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    shared_ptr<A> p, q;
    p = blah blah;
    q.reset (q.get ());
    Comme quoi, l'absence de conversion implicite (A* -> shared_ptr<A> et shared_ptr<A> -> A*) n'effraie pas certains : ils invoquent plusieurs fonctions membres nommée, pour "convertir" shared_ptr<A> en A* en shared_ptr<A>. (Si ils voulaient "convertir" un A en B, et que la seule fonction qui renvoie un B et prennent A s'appelle A::I_want_to_get_a_B_and_then_die_an_horrible_death(), ils feraient b = a.I_want_to_get_a_B_and_then_die_an_horrible_death(). )

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

Discussions similaires

  1. Relation entre classes
    Par IsraGab dans le forum C#
    Réponses: 2
    Dernier message: 31/05/2010, 16h12
  2. Réponses: 5
    Dernier message: 19/07/2009, 19h20
  3. Relations entre classes
    Par karim_sousse dans le forum Diagrammes de Classes
    Réponses: 2
    Dernier message: 29/06/2009, 13h24
  4. Relation Entre Class
    Par makaveli_12 dans le forum UML
    Réponses: 2
    Dernier message: 04/02/2009, 12h32
  5. Relation entre classe
    Par guimo26 dans le forum VB.NET
    Réponses: 5
    Dernier message: 25/11/2008, 15h08

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