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 :

variable membre et class


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 73
    Par défaut variable membre et class
    bonjour,

    un petit probleme de class.

    Pour passer a la vitesse superieure, et essayer d'arrêter de faire en sorte que mon code ressemble a un plat de spagghettis....j'ai reorganisé mon code pour le rendre plus modulaire.
    Et donc créé plus d'objet et donc de class.

    Malheureusement cela apporte aussi son lot d'erreur.

    Je vais tenter de faire simple.

    J'aurais besoin de recuperer une valeur issu d'une variable (private) d'une class A afin de pourvoir l'exploiter depuis un objet B (class B)

    J'ai ajouté ma class B (un pointeur) dans ma class A et créé l'objet, ça a l'air de marchouiller mais je dois changer ma variable de private vers public. De plus créer un objet pour recuperer une valeur de variable me parait disproportionné.

    Apres une question pareille, ais-je besoin de preciser que mon niveau :o)

    Comment peut on recuperer des valeurs de variable membre d'une class afin de les exploiter pour d'autres class ?

    J'ai Fait une recherche sur la FAQ C++ mais je ne sais pas l'imbrication des class l'une dans l'autre ets un bonne chose ou si je doit utiliser friend class (je n'en ai pas completement compris l'interet )

    Merci

  2. #2
    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
    Par défaut
    Bonjour,
    Citation Envoyé par barbarello Voir le message
    J'aurais besoin de recuperer une valeur issu d'une variable (private) d'une class A afin de pourvoir l'exploiter depuis un objet B (class B)
    La première question à se poser est: pourquoi B a besoin de cette variable. N'est-ce pas que B effectue une opération qui devrait être dans A? Si oui: alors plus de problème. Si non, alors allons pour la suite.

    Citation Envoyé par barbarello Voir le message
    J'ai ajouté ma class B (un pointeur) dans ma class A et créé l'objet, ça a l'air de marchouiller mais je dois changer ma variable de private vers public. De plus créer un objet pour recuperer une valeur de variable me parait disproportionné.
    J'ai l'impression qu'il y a des mélanges dans l'air. Quel est l'intérêt d'avoir une instance (et non une classe) de B dans A?
    Citation Envoyé par barbarello Voir le message
    Comment peut on recuperer des valeurs de variable membre d'une class afin de les exploiter pour d'autres class ?
    Réponse: les accesseurs.

    Citation Envoyé par barbarello Voir le message
    J'ai Fait une recherche sur la FAQ C++ mais je ne sais pas l'imbrication des class l'une dans l'autre ets un bonne chose ou si je doit utiliser friend class (je n'en ai pas completement compris l'interet )
    Beaucoup de mélange...
    Imbriquer une classe dans l'autre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class A{
    ...
       class B{
       }
    };
    Cela a de l'intérêt lorsque B n'est pertinent que pour des A.
    Mais peut être as-tu voulu dire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class A
    {
    ...
       B m_b;
    //ou
       B *m_pb;
    };
    C'est à ta conception de dire si ça a un intérêt. Mais aucunement si c'est juste pour modifier un paramètre de A depuis B.

    friend: FAQ.

    Enfin, vu le caractère un peu débutant de ton explication, je te conseille de poster un petit bout de code avec ce que tu souhaites faire pour qu'on puisse d'apporter plus d'info.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 73
    Par défaut
    vu le caractère un peu débutant de ton explication, je te conseille de poster un petit bout de code avec ce que tu souhaites faire pour qu'on puisse d'apporter plus d'info.
    ça tombe bien je suis dans la rubrique débuter !

    Malheureseument je ne peux poster du code pour le moment, pour cause de travail (mais si vous savez ! le truc pour gagner ++.....)

    Mais peut être as-tu voulu dire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class A
    {
    ...
       B m_b;
    //ou
       B *m_pb;
    };
    Oui c'est cela, je ne savais pas que le mot imbrication était déjà reservé
    Je déclare B *m_pb; car j'en ai besoin précédemment, ce n'est pas lié à mon problème actuel.

    J'ai juste une fonction membre de la class A qui utilise une variable membre de A, sauf que a un moment j'aurais voulu recuperer la valeur cette variable pour être utilisé dans une fonction membre d'une class B.

    Réponse: les accesseurs.
    Je testerais ce soir !



    Merci beaucoup de ta reponse

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

    Informations professionnelles :
    Activité : aucun

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

    L'amitié et les classes imbriquées sont deux choses tout à fait distinctes, et il faut donc bien comprendre ce que ca fait.

    En ce qui concerne l'amitié, son but est de dire que "tu fais suffisemment confiance au type ou à la fonction que tu déclare amie pour lui laisser l'accès intégral à l'ensemble de ce qui est normalement caché au reste du code"

    Utilisée de manière parcimonieuse et réfléchie, elle aura l'énorme avantage de te permettre de ne pas devoir fournir un accesseur ou un mutateur pour le membre d'un type qui ne servirait que pour un seul type ou une seule particulier(e) et qui ne devrait pas être accessible "au reste du code".

    Si tu en viens à déclarer des amitiés réciproques et dans tous les sens, tu peux en arriver à une situation dans laquelle "tous les types ont acces à l'ensemble du contenu des autres", et il est sans doute temps de te demander pourquoi tu as décidé de placer des membres en accessibilité privée ou protégée

    La notion de "classe imbriquée", quant à elle, est indissociable de la notion de "portée" du langage.

    la notion de "portée" du langage est celle qui a justifié la prise en compte des espaces de noms ou la décision de permettre aux classes et aux structures de contenir des fonctions membres.

    En effet, tu n'es pas sans savoir que, si tu définis un type (quel qu'il soit) en dehors de tout autre type et en dehors de tout espace de noms dans un fichier donné, tu ne pourra pas définir un type (quel qu'il soit) portant le même nom en dehors de tout autre type ou espace de noms dans un autre fichier:

    Une fois que tu as décidé de définir la classe A dans l'espace de noms global, tu ne peux pas décider de définir la structure, l'union ou l'énumération A dans l'espace de noms global, quel que soit le fichier dans lequel tu essayerais de le faire.

    Par contre, rien ne t'interdit de déclarer un autre type nommé A dans un espace de noms différent

    Pour faire la distinction entre les deux, tu déclarera tes variables du premier type A sous la forme de voire, pour etre tout à fait sur, alors que pour déclarer une variable du type A qui a été défini dans l'espace de noms (mettons NS), tu utilisera la syntaxe
    voireDe la même manière, si tu a défini une fonction foo() au sein de ton type A (car une fonction membre peut se trouver aussi bien dans une union, une structure ou une classe), tu devras fournir une instance d'objet au départ de laquelle appeler la fonction, sous la forme de
    ou, si mavar est un pointeur, sous la forme de L'exception concerne les fonctions (et membres) statiques, pour lesquels il peut suffir de préciser le type correspondant, par exemple, tu pourra accéder aux membres et fonctions de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct MaStruct
    {
        static type field;
        static void staticFoo();
    };
    sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaStruct::field /*...*/
    MaStruct::staticFoo();
    ou sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    MaStruct  s;
    s.field;
    s.staticFoo();
    car tant le champs field que la fonction staticFoo ne dépendent d'aucune instance de la structure MaStruct.

    La création de types imbriqués (car les structures, les classes, les unions, les énumérations et les alias de types (typedefs) peuvent être imbriqués) dans un autre (car les structures, les classes et les unions peuvent contenir un type imbriqué) aura un résultat finalement fort semblable au fait de définir un type au sein d'un espace de noms: pour pouvoir créer une instance du type imbriqué, il faudra passer par... le nom du type dans lequel il est imbriqué.

    Il n'y a donc aucun problème à déclarer deux structures proches de
    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
    struct A
    {
        struct Nested
        {
            /* contenu de la structure imbriquee /*
        };
        /* contenu de la structure A */
    };
    struct B
    {
        struct Nested
        {
            /* contenu de la structure imbriquee /*
        };
        /* contenu de la structure A */    
    };
    car pour créer une instance de la structure Nested définie dans A, tu devra écrire
    alors que pour créer une instance de la structure Nested definie dans B, ce serait
    Si, au lieu d'avoir choisi le nom "Nested" pour la structure imbriquée, j'avais décidé de choisir le nom "Error", tu te serais rendu compte que A::Error aurait représenté... une erreur dans le contexte d'un travail propre à A, alors que B::Error aurait représenté... une erreur dans le contexte d'un travail propre à B

    Il reste que l'accessibilité des structures imbriquées (privée, protégée ou publique) est celle de l'accessibilité dans laquelle elles sont définies.

    Ainsi, si tu définis une structure imbriquée dans l'accessibilité public: d'une classe, cette structure sera accessible depuis l'ensemble du code, alors que si tu la défini dans l'accessibilité private: de la classe, elle ne sera accessible qu'au départ des fonction membre de cette classe.

    A défaut d'avoir pu te dire si l'amitié ou les classes imbriquées sont intéressantes dans ton cas, j'espère avoir contribué au fait que tu es maintenant en mesure de déterminer si ce sont des pratiques qui te sont utiles, et à voir quand il te faudra y recourir
    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
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 73
    Par défaut
    Merci pour cette explication !

    On dirait qu'elle pique les yeux au départ mais en prêtant attention (j'ai dû la relire plusieurs fois..) ça a clarifié certains points pour moi !

  6. #6
    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
    Par défaut
    Citation Envoyé par barbarello Voir le message
    Oui c'est cela, je ne savais pas que le mot imbrication était déjà reservé
    C'est pas le mot imbrication qui est réservé, c'est la différence entre classe et instance.
    Quand tu dis la classe B est imbriquée dans la classe A, je comprends:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class A
    {
    ...
        class B{
        };
    };
    Quand tu veux dire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class A
    {
    ...
        B *m_pb;
    // ou
        B m_b;
    };
    il vaut mieux dire: ma classe A possède un membre de type B.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 73
    Par défaut
    C'est pas le mot imbrication qui est réservé, c'est la différence entre classe et instance.
    Oui j'avais compris ce que tu voulais dire.

    Par contre je pensais avoir compris comment arriver a mes fins mes j'avais tout faux.

    Je vais exposer mon probleme autrement:

    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 A
    {
        private:
        int m_number1;
     
       public:
       A();
       int GetNumber(){ return m_number;}
    };
     
     
     
    class B
    {
      private:
      int m_number2;
     
      public:
      B();
      void Fonction2(void);
      void Fonction1(int value);
    };

    Je cherche a appeler Fonction en lui passant pour parametre la valeur retour de GetNumber.

    J'ai essayé en créant une instance (j'espere que j'ai bon dans le nomage ) mais le resultat est faux. De plus c'est aussi faux mais différent lorsque j'utilise un pointeur.
    l'appelle se faisant depuis une méthode appartenant a class B

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void B::Fonction(void)
    {
     A test;
     m_number2= test.GetNumber();
     Fonction1(m_number2);
    }

    En esperant que quelqu'un ai compris le principe de ce que je voulais, car etant vraiment debutant, j'ai peur que le code exact embrouille encore et surtout fasse rire....

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

    Informations professionnelles :
    Activité : aucun

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

    Là, tu essaye d'affecter à un membre de ta classe B le membre (potentiellement non initialisé) d'une variable... temporaire.

    Si cela peut encore passer avec les types primitifs (dont les "int"), c'est un comportement à risque dés que tu travaille avec des types abstraits de données (qu'il s'agisse d'unions, de structures ou de classe).

    Ce qui pourrait fonctionner, selon le schéma que tu propose serait ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        A monA;
        /* veiller à ce que monA.m_number1 ait la valeur adéquate*/
        B monB;
        monB.Fonction1(monA.GetNumber());
    }
    Si tu souhaite, effectivement, initialiser directement les variables de type B avec une valeur obtenues au départ d'une variable de type A, il te reste toujours la possibilié de définir un constructeur pour ta classe B prenant comme argument une référence de type A, en prenant soin (pour éviter les problèmes) de définir ce constructeur comme explicite.

    Cela pourrait donner:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    class A
    {
        public:
            /* le constructeur sans argument: m_nombre a une valeur par défaut*/
            A():m_nombre(0){}
            /* un constructeur par lequel nous donnons directement la valeur
             * qui nous intéresse à m_nombre
             */
            A(int n):m_nombre(n){}
            /* l'accesseur */
            int getNombre() const{return m_nombre;}
            /* le mutateur (mais, est-il réellement utile ??? */
            void setNombre(int n){ m_nombre = n;}
        private:
            int m_nombre;
    };
    class B
    {
        public:
            /* un constructeur ne prenant pas d'argument, le membre est initialisé
             * avec une valeur par défaut
             */
            B():m_membre(0){}
            /* un constructeur par lequel nous donnons une valeur intéressante
             * au membre
             */
            B(int n):m_membre(n){}
            /* un constructeur qui utilise la classe A pour donner la valeur utile
             * surtout ici, il faut éviter les ambiguités, et donc déclarer ce
             * constructeur exiplict
             */
            explicit B(const A& a):m_membre(a.getNombre()){}
            void fonction1(int i)
            {
                std::cout<<i<<std::endl;
            }
            void fonction2(const A& a)
            {
                std::cout<<a.getNombre()<<std::endl;
            }
            int getMembre() const{return m_membre;}
        private:
            int m_membre;
    };
    Ici, j'ai prévu trois constructeur différents, voyons ce qui peut fonctionner
    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
     
    int main ()
    {
        B premier; //ok: constructeur sans argument: m_membre vaut 0
        B second(3); // ok: constructeur prenant un int
        A monA(10);
        B troisieme(monA); // ok: constructeur prenant un A
        premier.fonction1(monA.getNombre()); //ok: A::getNombre renvoie
                                             // bien un int
        second.fonction2(monA); // ok, on passe un A
        troisieme.fonction2(5); //??? ca fonctionne...
                                // le fait de déclarer un argument sous la
                                // forme d'une référence constante permet la
                                // création d'une variable temporaire du type
                                // adéquat, et, ici, il existe un A::A(int)...
        return 0;
    }
    Magique, non
    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

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 73
    Par défaut
    Vraiment merci beaucoup pour le temps passé.

    Je vais me poser devant les explications fournies et trouver mon bonheur...

    ........................................

    Et donc effectivement quand j'applique ce que j'ai lu a un programme simple (une appli console C++), ça marche bien..je n'ai même pas eu besoin de relire ton code .
    C'est signe que j'en ai compris le principe

    Si j'applique la même chose a mon code en cours (basé sur la bibliotheque wxWidgets) ce n'est plus la même histoire.

    Bref encore merci, je n'ai plus qu'a me creuser la tête....

  10. #10
    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
    Par défaut
    Si tu as un problème spécifique wxWidget, sache qu'il existe un forum pour cette bibliothèque.

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

Discussions similaires

  1. Problème de variable membre en pointeur dans une classe
    Par medrimonia dans le forum Langage
    Réponses: 2
    Dernier message: 09/06/2012, 18h00
  2. Fonctions et variables membre d'une classe
    Par dida_plt dans le forum Débuter
    Réponses: 1
    Dernier message: 20/03/2012, 16h21
  3. Réponses: 10
    Dernier message: 20/03/2009, 10h39
  4. [POO] Classe abstraite PHP5 et variables membres
    Par Invité dans le forum Langage
    Réponses: 3
    Dernier message: 07/06/2006, 01h27
  5. Réponses: 6
    Dernier message: 06/10/2004, 12h59

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