Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème vis-à-vis d'un objet dans un autre

Cours sur les Classes

Sujet résolu
    16 septembre 2018 à 1:41:49

    Bonsoir à toutes et tous!

    Il est sûrement très tard mais je me permets de poser mon problème. Voilà donc je suis dans le cours des classes d'OpenClassroom et je suis confronté à un souci plutôt embêtant. En effet, dans le cours on aborde les objets d'une classe à l'intérieur d'une autre pour les lier et les utiliser. Dans l'exemple du cours on a ça:

    (Personnage.h)

    #ifndef DEF_PERSONNAGE
    #define DEF_PERSONNAGE
     
    #include <iostream>
    #include <string>
    #include "Arme.h" //Ne PAS oublier d'inclure Arme.h pour en avoir la définition
     
    class Personnage
    {
        public:
     
        Personnage();
        Personnage(std::string nomArme, int degatsArme);
        ~Personnage();
        void recevoirDegats(int nbDegats);
        void attaquer(Personnage &cible);
        void boirePotionDeVie(int quantitePotion);
        void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
        bool estVivant() const;
     
     
        private:
     
        int m_vie;
        int m_mana;
        Arme m_arme; //Notre Personnage possède une Arme
    };
     
    #endif

    dont Arme.h correspond à ceci :

    #ifndef DEF_ARME
    #define DEF_ARME
    
    #include <iostream>
    #include <string>
     
    class Arme
    {
        public:
     
        Arme();
        Arme(std::string nom, int degats);
        void changer(std::string nom, int degats);
        void afficher() const;
     
        private:
     
        std::string m_nom;
        int m_degats;
    };
     
    #endif

    Dans le Programme.cpp on voulait remplacer les anciens membres m_arme et m_degats par l'objet m_arme de la Classe Arme, or les équivalents des anciens membres dans le nouvel objet sont private. Le cours propose du coup d'utiliser un accesseur getDegats qui permettrait d'aller chercher et retourner m_degats :

    int Arme::getDegats() const
    {
        return m_degats;
    }

    Je comprends bien pourquoi c'est nécessaire, on doit garder l'attribut private donc accéder à cette donnée n'est que possible par un accesseur. Cependant le m_nom est un private aussi mais il n'y a pas d'accesseur associé et il n'en parle pas. 

    (mon Programme.cpp)

    #include "Personnage.h"
    #include <string>
    #include <iostream>
    #include "Arme.h"
    
    
    Personnage::Personnage() : m_vie(100), m_mana(100)
    {
    
    }
    
    Personnage::Personnage(string nomArme, int degatsArme) : m_vie(100), m_mana(100),m_arme(nomArme, degatsArme)
    {
    
    }
    
        void Personnage::attaquer (Personnage &cible)
        {
            cible.recevoirDegats(m_arme.getDegats());
        }
    
        void Personnage::boirePotionDeVie (int quantitePotion)
        {
            m_vie=m_vie+quantitePotion;
            if(m_vie>100)
            {
                m_vie=100;
            }
        }
    
        void Personnage::changerArme (string nouvelleArme, int nouveauDegat)
        {
            m_arme.m_nom=nouvelleArme;
            m_arme.m_degats=nouveauDegat;
        }
    
        
    
    

    Surtout que chaque fois j'essaie de compiler ceci, j'ai une erreur qui précise que m_nom est un private. Ai-je mal compris quelque chose? Je suis relativement nouveau aux classes donc pardonnez mes questions "bêtes", j'essaie juste d'apprendre le max. 

    Merci encore à ceux qui veulent m'aider, j'essaierai d'éviter de refaire les mêmes erreurs !

    Bonne soirée!




    • Partager sur Facebook
    • Partager sur Twitter
      16 septembre 2018 à 2:46:59

      Re-Hello,

      Plutôt que d'essayer de changer les attributs de l'arme, initialise-en une nouvelle et écrase l'ancienne :

      void Personnage::changerArme (string nouvelleArme, int nouveauDegat)
      {
          m_arme = Arme{nouvelleArme, nouveauDegat};
      }

      Bon, dans ton post précédent je t'ai dis que ce cours était mauvais, en voilà une preuve, c'est stupide cette façon de faire parce que le jour où la classe Arme comportera plus de statistiques "essentielles", ba tu seras obligé de modifier la signature de la fonction changerArme(...) pour l'adapter. Et ça c'est pas cool :D.

      Idéalement la fonction devrait se présenter de cette manière :

      void Personnage::changerArme(const Arme& a)
      {
          m_arme = a;
      }

      Ce qui permet ensuite d'attribuer une arme comme cela :

      Arme a{"Dandelion", 100};
      perso.changerArme(a);
      
      // ou
      
      perso.changerArme(Arme{"Dandelion", 100});

      De cette façon, même si tu ajoutes des attributs dans la classe Arme, tu ne seras pas obligé de modifier la fonction changerArme(...) dans la classe Personnage mais seulement les spécifier lors de la construction de celle-ci.

      Après il y aurait beaucoup de choses à dire concernant la conception générale mais il est tard et j'ai une flemme olympique ^^.

      -
      Edité par Guit0Xx 16 septembre 2018 à 3:11:15

      • Partager sur Facebook
      • Partager sur Twitter

      ...

        16 septembre 2018 à 3:09:30

        Bonsoir,

        Pour compléter la réponse de Guit0Xx, j'ajouterais que dans ton cas, l'erreur vient précisément de ces lignes :

        m_arme.m_nom=nouvelleArme;
        m_arme.m_degats=nouveauDegat;

        En effet, tu cherches ici à accéder aux attributs privés de la classe Arme, ce qui n'est pas possible.

        Guit0Xx, j'aimerais comprendre pourquoi des accolades ici : ?

        m_arme = Arme{nouvelleArme, nouveauDegat};


        Et il me semble que beaucoup proposent ce cours en alternative à celui d'OC : http://guillaume.belz.free.fr/doku.php?id=programmez_avec_le_langage_c

        -
        Edité par Cypher__ 16 septembre 2018 à 3:13:49

        • Partager sur Facebook
        • Partager sur Twitter
          16 septembre 2018 à 3:18:09

          Les accolades sont un moyen introduit en C++11 (2011) pour construire des objets dont voici les avantages: https://zestedesavoir.com/forums/sujet/5876/debuter-en-c/#p107110

          Vu la tronche de Arme, j'aurais tendance à en faire une bête structure sans fonction membre. De toute manière la moitié des fonctions présentes n'ont pas de sens.

          • Partager sur Facebook
          • Partager sur Twitter
            16 septembre 2018 à 3:30:46

            jo_link_noir a écrit:

            Les accolades sont un moyen introduit en C++11 (2011) pour construire des objets dont voici les avantages: https://zestedesavoir.com/forums/sujet/5876/debuter-en-c/#p107110

            Vu la tronche de Arme, j'aurais tendance à en faire une bête structure sans fonction membre. De toute manière la moitié des fonctions présentes n'ont pas de sens.


            Merci beaucoup, je vais voir ça de plus près.

            Certes, mais l'objectif était ici de comprendre l'utilisation des accesseurs, pas de faire quelque chose avec du sens ... 

            • Partager sur Facebook
            • Partager sur Twitter
              16 septembre 2018 à 4:07:44

              awinner100 a écrit:

              Et il me semble que beaucoup proposent ce cours en alternative à celui d'OC : http://guillaume.belz.free.fr/doku.php?id=programmez_avec_le_langage_c

              Oui, il a l'avantage d'être à jour et en français. Petite pécision quand même, il est en cours d'écriture mais il y a déjà tout ce qu'il faut pour bien démarrer et avoir une bonne base.

              Après si l'anglais ne te fait pas peur, je ne peux que te conseiller le bouquin C++ Primer 5th de S. Lippman. Avec ça tu auras une base bien solide. Bon par contre il date un peu (norme C++ 11), mais ce n'est pas vraiment un problème.

              awinner100 a écrit:

              Certes, mais l'objectif était ici de comprendre l'utilisation des accesseurs, pas de faire quelque chose avec du sens...

              C'est quand même mieux d'apprendre des choses qui ont du sens.

              Bon maintenant que tu le dis, c'est vrai que j'aurai pu expliquer dans ma réponse que si il obtenait cette erreur c'était parce qu'on ne pouvait pas accéder/modifier directement les données privées d'une classe et que pour cela il fallait passer par un getter. Mais étant donné que c'est quelque chose que l'on doit éviter, par réflexe je n'y ai pas pensé.

              -
              Edité par Guit0Xx 16 septembre 2018 à 4:31:53

              • Partager sur Facebook
              • Partager sur Twitter

              ...

              Problème vis-à-vis d'un objet dans un autre

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown