Partage
  • Partager sur Facebook
  • Partager sur Twitter

Manque d'héritage en POO

error: class 'classe' does not have any field named 'attribut'

Sujet résolu
    5 juillet 2023 à 13:24:39

    Bonjour

    Je dispose en tout de 7 fichiers :

    Guerrier.cpp:
    #include "Guerrier.h"
    #include <iostream>
    
    using namespace std;
    
    Guerrier::Guerrier(string nom) : m_nom(nom){}
    
    void Guerrier::sePresenter() const
    {
        cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
        cout << "J'ai encore " << m_vie << " points de vie." << endl;
        cout << "Je suis un Guerrier redoutable." << endl;
    }
    Magicien.cpp :
    #include "Magicien.h"
    #include <iostream>
    
    using namespace std;
    
    //Magicien::Magicien() : Personnage(), m_mana(100)
    //{
    //
    //}
    
    //remonter des paramètres d'un constructeur à un autre
    Magicien::Magicien(string nom) : Personnage(nom), m_mana(100)
    {
    
    }
    main.cpp :
    #include <iostream>
    #include "Personnage.h"
    #include "Guerrier.h"
    #include "Magicien.h"
    #include <string>
    
    using namespace std;
    
    int main()
    {
        Personnage marcel("Marcel");
        marcel.sePresenter();
        Guerrier perceval("Perceval");
        perceval.sePresenter();
    }
    Personnage.cpp :
    #include <iostream>
    #include "Personnage.h"
    
    using namespace std;
    
    //Personnage::Personnage() : m_vie(100), m_nom("Jack")
    //{
    //
    //}
    
    //remonter des paramètres d'un constructeur à un autre
    Personnage::Personnage(string nom) : m_vie(100), m_nom(nom)
    {
    
    }
    
    void Personnage::recevoirDegats(int degats)
    {
        m_vie -= degats;
    }
    
    void Personnage::coupDePoing(Personnage &cible) const
    {
        cible.recevoirDegats(10);
    }
    
    void Personnage::sePresenter() const
    {
        cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
        cout << "J'ai encore " << m_vie << " points de vie." << endl;
    }
    Guerrier.h :
    #ifndef GUERRIER_H_INCLUDED
    #define GUERRIER_H_INCLUDED
    
    #include "Personnage.h"//Ne pas oublier d'inclure Personnage.h pour pouvoir en hériter !
    
    class Guerrier : public Personnage//Signifie : créer une classe Guerrier qui hérite de
    {                                 //la classe Personnage
        public:
            Guerrier(std::string nom);//il faut aussi changer le constructeur quand on
                                      //des paramètres par défaut dans la classe mère
            void frapperAvecUnMarteau() const;//Méthode qui ne concerne que les guerriers
            void sePresenter() const;
    };
    
    #endif // GUERRIER_H_INCLUDED
    Magicien.h :
    #ifndef MAGICIEN_H_INCLUDED
    #define MAGICIEN_H_INCLUDED
    
    #include "Personnage.h"
    
    class Magicien : public Personnage
    {
        public:
            Magicien(std::string nom);//il faut aussi changer le constructeur quand on
                                      //des paramètres par défaut dans la classe mère
    
            void bouleDeFeu() const;
            void bouleDeGlace() const;
    
        private:
            int m_mana;
    };
    
    #endif // MAGICIEN_H_INCLUDED
    Personnage.h :
    #ifndef PERSONNAGE_H_INCLUDED
    #define PERSONNAGE_H_INCLUDED
    
    #include <string>
    
    class Personnage
    {
        public:
            Personnage();
            Personnage(std::string nom);
            void recevoirDegats(int degats);
            void coupDePoing(Personnage &cible) const;
    
            void sePresenter() const;
    
    //    private:
        protected: //Privé, mais accessible aux éléments enfants (Guerrier, Magicien)
            int m_vie;
            std::string m_nom;
    };
    
    #endif // PERSONNAGE_H_INCLUDED
    Les classes de Magicien, et de Guerrier héritent de celle de Personnage. Le problème est que le code ne fonctionne pas et affiche l'erreur suivante :
    Par contre, lorsque je décommente les deux dernières instructions dans le main ainsi que la définition du constructeur dans le Guerrier.cpp, le code fonctionne :
    #include <iostream>
    #include "Personnage.h"
    #include "Guerrier.h"
    #include "Magicien.h"
    #include <string>
    
    using namespace std;
    
    int main()
    {
        Personnage marcel("Marcel");
        marcel.sePresenter();
    //    Guerrier perceval("Perceval");
    //    perceval.sePresenter();
    }
    #include "Guerrier.h"
    #include <iostream>
    
    using namespace std;
    
    //Guerrier::Guerrier(string nom) : m_nom(nom){}
    
    void Guerrier::sePresenter() const
    {
        cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
        cout << "J'ai encore " << m_vie << " points de vie." << endl;
        cout << "Je suis un Guerrier redoutable." << endl;
    }
    

    Sans avoir encore testé dans le main si la classe Magicien marche, je comprends donc que l'erreur se trouve au niveau du constructeur de Guerrier, mais je n'arrive pas à trouver ce qu'il manque. Que manque-t-il afin que l'objet guerrier soit déclaré ?
    Cordialement

    -
    Edité par 1Stark 5 juillet 2023 à 13:25:36

    • Partager sur Facebook
    • Partager sur Twitter
      5 juillet 2023 à 14:40:30

      1Stark a écrit:

      Que manque-t-il afin que l'objet guerrier soit déclaré ?

      L'appel du constructeur de la classe mère. C'est lui qui initialise m_nom.

      A partir ce C++11 Tu peux le faire facilement avec le mot clé using :

      class Guerrier : public Personnage//Signifie : créer une classe Guerrier qui hérite de
      {                                 //la classe Personnage
          public:
              using Personnage::Personnage;
              //Guerrier(std::string nom);//il faut aussi changer le constructeur quand on
                                        //des paramètres par défaut dans la classe mère
              void frapperAvecUnMarteau() const;//Méthode qui ne concerne que les guerriers
              void sePresenter() const;
      };

      et tu enlèves le constructeur de Guerrier.

      //Guerrier::Guerrier(string nom) : Personnage(nom){}
      
      void Guerrier::sePresenter() const
      {
          cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
          cout << "J'ai encore " << m_vie << " points de vie." << endl;
          cout << "Je suis un Guerrier redoutable." << endl;
      }




      • Partager sur Facebook
      • Partager sur Twitter
      ...
        5 juillet 2023 à 19:15:14

        Il manque un "virtual" sur la déclaration de "sePresenter" dans la classe "Personnage", et un "override" sur la déclaration de la même fonction de la classe "Guerrier"
        • Partager sur Facebook
        • Partager sur Twitter

        Si vous ne trouvez plus rien, cherchez autre chose.

          6 juillet 2023 à 13:24:16

          Bonjour

          @dragonjoker le code à l'air de pourtant bien fonctionner. Pourquoi manque-t-il ces instructions et de quelle manière devrais-je les placer ?

          Cordialement

          -
          Edité par 1Stark 6 juillet 2023 à 13:25:20

          • Partager sur Facebook
          • Partager sur Twitter
            6 juillet 2023 à 13:37:33

            Comme vous n'avez pas spécifier que la fonction "sePresenter" est virtuelle, le compilateur cherche à déterminer la fonction qui sera appelée dès la compilation et non mettre en place les informations qui permettraient de déterminer à l'exécution si c'est "Personnage::sePresenter" ou une redefinition de la fonction "sePresenter" dans une des classes dérivée de "Personnage".

            Résultat, quand Perceval se présente, ce n'est pas "un Guerrier redoutable" mais un simple péquin moyen, si vous le mélanger avec les autres personnages.

            Personnage perceval = Guerrier("Perceval");
            perceval.sePresenter();



            -
            Edité par bacelar 6 juillet 2023 à 13:40:11

            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              6 juillet 2023 à 15:06:14

              @bacelar @dragonjoker Dans Guerrier.cpp j'ai placé un démasquage comme ceci :

              #include "Guerrier.h"
              #include <iostream>
              
              using namespace std;
              
              //Guerrier::Guerrier(string nom) : m_nom(nom){}
              
              ////masquage: appelle la fonction sePresenter à la place de celle de Personnage
              //void Guerrier::sePresenter() const
              //{
              //    cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
              //    cout << "J'ai encore " << m_vie << " points de vie." << endl;
              //    cout << "Je suis un Guerrier redoutable." << endl;
              //}
              
              //démasquage: on fait comme juste au-dessus sauf qu'on fait appel à la fonction
              //sePresenter de Personnage à l'intérieur de celle de Guerrier et on ajoute une ligne
              void Guerrier::sePresenter() const
              {
                 Personnage::sePresenter();
                  cout << "Je suis un Guerrier redoutable." << endl;
              }

              Si je m'y prend comme ceci pour placer le virtual et le override est-ce correct ?

              #ifndef PERSONNAGE_H_INCLUDED
              #define PERSONNAGE_H_INCLUDED
              
              #include <string>
              
              class Personnage
              {
                  public:
                      Personnage();
                      Personnage(std::string nom);
                      void recevoirDegats(int degats);
                      void coupDePoing(Personnage &cible) const;
              
                      virtual void sePresenter() const;
              
              //    private:
                  protected: //Privé, mais accessible aux éléments enfants (Guerrier, Magicien)
                      int m_vie;
                      std::string m_nom;
              };
              
              #endif // PERSONNAGE_H_INCLUDED
              #ifndef GUERRIER_H_INCLUDED
              #define GUERRIER_H_INCLUDED
              
              #include "Personnage.h"//Ne pas oublier d'inclure Personnage.h pour pouvoir en hériter !
              
              class Guerrier : public Personnage//Signifie : créer une classe Guerrier qui hérite de
              {                                 //la classe Personnage
                  public:
                      using Personnage::Personnage;//appel du constructeur de la classe mère pour initialiser m_nom
                      //Guerrier(std::string nom);//il faut aussi changer le constructeur quand on a
                                                //des paramètres par défaut dans la classe mère
                      void frapperAvecUnMarteau() const;//Méthode qui ne concerne que les guerriers
                      override void sePresenter() const;
              };
              
              #endif // GUERRIER_H_INCLUDED

              Cordialement

              -
              Edité par 1Stark 6 juillet 2023 à 16:15:15

              • Partager sur Facebook
              • Partager sur Twitter
                6 juillet 2023 à 16:13:10

                Tu n'en est peut-être pas arrivé là dans ton apprentissage, mais le mot clé virtual sert pour le polymorphisme.

                Il se place dans la déclaration de la fonction membre de la classe de base, ex : pour personnage

                        virtual void sePresenter() const;

                Et on met le mot clé sur la fonction membre redéfinie de la classe dérivé ex : pour guerrier

                        void sePresenter() const override;

                Ça n'a pas d'incidence pour toi pour l'instant car tu utilises des objets créé sur la pile.

                Regarde un cours sur le polymorphisme pour plus d'explications.

                • Partager sur Facebook
                • Partager sur Twitter
                ...
                  6 juillet 2023 à 16:27:07

                  Je vois et merci infiniment à tous les aideurs. Le programme est bien opérationnel :

                  fichier Guerrier.cpp :

                  #include "Guerrier.h"
                  #include <iostream>
                  
                  using namespace std;
                  
                  //Guerrier::Guerrier(string nom) : m_nom(nom){}
                  
                  ////masquage: appelle la fonction sePresenter à la place de celle de Personnage
                  //void Guerrier::sePresenter() const
                  //{
                  //    cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
                  //    cout << "J'ai encore " << m_vie << " points de vie." << endl;
                  //    cout << "Je suis un Guerrier redoutable." << endl;
                  //}
                  
                  //démasquage: on fait comme juste au-dessus sauf qu'on fait appel à la fonction
                  //sePresenter de Personnage à l'intérieur de celle de Guerrier et on ajoute une ligne
                  void Guerrier::sePresenter() const
                  {
                     Personnage::sePresenter();
                      cout << "Je suis un Guerrier redoutable." << endl;
                  }

                  fichier Magicien.cpp :

                  #include "Magicien.h"
                  #include <iostream>
                  
                  using namespace std;
                  
                  //Magicien::Magicien() : Personnage(), m_mana(100)
                  //{
                  //
                  //}
                  
                  //remonter des paramètres d'un constructeur à un autre
                  Magicien::Magicien(string nom) : Personnage(nom), m_mana(100)
                  {
                  
                  }

                  fichier main.cpp :

                  #include <iostream>
                  #include "Personnage.h"
                  #include "Guerrier.h"
                  #include "Magicien.h"
                  #include <string>
                  
                  using namespace std;
                  
                  int main()
                  {
                      Personnage marcel("Marcel");
                      marcel.sePresenter();
                      Guerrier perceval("Perceval");
                      perceval.sePresenter();
                  }

                  fichier Personnage.cpp :

                  #include <iostream>
                  #include "Personnage.h"
                  
                  using namespace std;
                  
                  //Personnage::Personnage() : m_vie(100), m_nom("Jack")
                  //{
                  //
                  //}
                  
                  //remonter des paramètres d'un constructeur à un autre
                  Personnage::Personnage(string nom) : m_vie(100), m_nom(nom)
                  {
                  
                  }
                  
                  void Personnage::recevoirDegats(int degats)
                  {
                      m_vie -= degats;
                  }
                  
                  void Personnage::coupDePoing(Personnage &cible) const
                  {
                      cible.recevoirDegats(10);
                  }
                  
                  void Personnage::sePresenter() const
                  {
                      cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
                      cout << "J'ai encore " << m_vie << " points de vie." << endl;
                  }
                  

                  fichier Guerrier.h :

                  #ifndef GUERRIER_H_INCLUDED
                  #define GUERRIER_H_INCLUDED
                  
                  #include "Personnage.h"//Ne pas oublier d'inclure Personnage.h pour pouvoir en hériter !
                  
                  class Guerrier : public Personnage//Signifie : créer une classe Guerrier qui hérite de
                  {                                 //la classe Personnage
                      public:
                          using Personnage::Personnage;//appel du constructeur de la classe mère pour initialiser m_nom
                          //Guerrier(std::string nom);//il faut aussi changer le constructeur quand on a
                                                    //des paramètres par défaut dans la classe mère
                          void frapperAvecUnMarteau() const;//Méthode qui ne concerne que les guerriers
                          void sePresenter() const override;
                  };
                  
                  #endif // GUERRIER_H_INCLUDED

                  fichier Magicien.h :

                  #ifndef MAGICIEN_H_INCLUDED
                  #define MAGICIEN_H_INCLUDED
                  
                  #include "Personnage.h"
                  
                  class Magicien : public Personnage
                  {
                      public:
                          Magicien(std::string nom);//il faut aussi changer le constructeur quand on
                                                    //des paramètres par défaut dans la classe mère
                  
                          void bouleDeFeu() const;
                          void bouleDeGlace() const;
                  
                      private:
                          int m_mana;
                  };
                  
                  #endif // MAGICIEN_H_INCLUDED

                  fichier Personnage.h :

                  #ifndef PERSONNAGE_H_INCLUDED
                  #define PERSONNAGE_H_INCLUDED
                  
                  #include <string>
                  
                  class Personnage
                  {
                      public:
                          Personnage();
                          Personnage(std::string nom);
                          void recevoirDegats(int degats);
                          void coupDePoing(Personnage &cible) const;
                  
                          virtual void sePresenter() const;
                  
                  //    private:
                      protected: //Privé, mais accessible aux éléments enfants (Guerrier, Magicien)
                          int m_vie;
                          std::string m_nom;
                  };
                  
                  #endif // PERSONNAGE_H_INCLUDED

                  Cordialement








                  -
                  Edité par 1Stark 6 juillet 2023 à 16:27:48

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Manque d'héritage en POO

                  × 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