Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème classe personnage

leur donner un nom

    22 octobre 2018 à 11:16:35

    Bonjour

    Je suis entrain de m'exercer à créer un petit jeu et aimerait pouvoir demander (à l'utilisateur) comment doit s'appeler le personnage. Dans mon Personnage.h

    #ifndef DEF_PERSONNAGE
    #define DEF_PERSONNAGE
    
    #include <iostream>
    #include <string>
    #include "Arme.h"
    
    class Personnage
    {
        public:
    
        Personnage();
        Personnage(std::string nomArme, int degatsArme);
        void recevoirDegats(int nbDegats);
        void attaquer(Personnage &cible);
        void seSoigner(int quantiteSoin);
        void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
        bool estVivant() const;
        void afficherEtat() const;
    
        private:
    
        int m_vie;
        Arme m_arme;
        std::string m_nom;
    };
    
    #endif
    

    que voici, j'ai créé un attribut pour le nom.

    Le problème est que je ne sais pas comment l'implémenter dans le constructeur pour permettre tout de même une modification demandée par un cin plus tard... 

    Je vous mets mon constructeur.

    Personnage::Personnage() : m_vie(100), m_nom()
    {
    
    }

    Là j'ai rien mis dans le m_nom car je sais pas quoi mettre. Merci d'avance.

    • Partager sur Facebook
    • Partager sur Twitter

    C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

      22 octobre 2018 à 11:23:24

      Sakut, je suis pas sur d'avoir compris la question.

      Pourquoi tu met pas tout simplement un "std::cin >> m_nom" dans ton constructeur ? 

      • Partager sur Facebook
      • Partager sur Twitter
        22 octobre 2018 à 11:24:59

        Parce que je savais pas qu'on pouvait faire ça...

        Re, j'ai fait ce que tu m'as dis

        Personnage::Personnage() : m_vie(100), std::cin >> m_nom
        {
        
        }

        mais à la compilation il me met le message d'erreur : "error : expected class-name before '>>' token", ce que je traduis par "un nom de classe est attendu avant les chevrons"...

        -
        Edité par RomainBricout 22 octobre 2018 à 11:31:44

        • Partager sur Facebook
        • Partager sur Twitter

        C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

          22 octobre 2018 à 11:38:23

          Personnage::Personnage() : m_vie(100)
          {
            std::cin >> m_nom;
          }
          • Partager sur Facebook
          • Partager sur Twitter
            22 octobre 2018 à 11:43:48

            Merci beaucoup

            • Partager sur Facebook
            • Partager sur Twitter

            C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

              22 octobre 2018 à 13:17:17

              Salut,

              Alors certes c'est possible de faire ça, mais ça ne me paraît pas pertinent, je ne pense pas que ça fasse partie des responsabilités de la classe "Personnage" de gérer la saisie, d'ailleurs ça impose la méthode d'acquisition du nom, alors qu'on pourrait vouloir le charger depuis un fichier ou le figer en littéral dans le code. Je pense que ça dois être fait en externe de la classe.

              Si le nom est obligatoire (ça me parait être le cas), alors il doit apparaître dans le constructeur et ensuite une fonction membre peut permettre de le renommer éventuellement. ça donne quelque chose comme ça

              #ifndef DEF_PERSONNAGE
              #define DEF_PERSONNAGE
               
              #include <iostream>
              #include <string>
              #include "Arme.h"
               
              class Personnage
              {
                  public:
               
                  Personnage() = delete;
                  Personnage(std::string nomPersonnage);
                  Personnage(std::string nomPersonnage, std::string nomArme, int degatsArme);
                  void recevoirDegats(int nbDegats);
                  void attaquer(Personnage &cible);
                  void seSoigner(int quantiteSoin);
                  void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
                  bool estVivant() const;
                  void afficherEtat() const;
              
                  void renommer(std::string nouveau_nom);
               
                  private:
               
                  int m_vie;
                  Arme m_arme;
                  std::string m_nom;
              };
               
              #endif



              Si on t'a pas encore fait le topo, le cours d'OC sur le C++ est mauvais, il est obsolète, contient des erreurs de conception et des mauvaise pratique, cet exemple/exercice en fait d'ailleurs parti. Une recherche sur le forum te donnera plus d'info

              • Partager sur Facebook
              • Partager sur Twitter
              Dream on, Dream on, Dream until your dream comes true
                22 octobre 2018 à 15:43:29

                Salut, en ce qui concerne le cours j'ai appris hier qu'il était mauvais.

                En ce qui concerne le code, je ne comprends les lignes :

                Personnage() = delete; // 1)
                
                Personnage(std::string nomPersonnage);
                    Personnage(std::string nomPersonnage, std::string nomArme, int degatsArme); // 2)
                /*
                
                ici je ne comprends pas pourquoi faire deux constructeurs contenant le std::string nomPersonnage.
                
                */
                

                peux tu m'éclairer sur ces dernières stp

                -
                Edité par RomainBricout 22 octobre 2018 à 15:44:21

                • Partager sur Facebook
                • Partager sur Twitter

                C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                  22 octobre 2018 à 15:59:09

                  1)

                  Le specifier delete te permet de préciser que cette fonction ne doit pas exister, car le compilateur génère par défaut les constructeurs par défaut et par copie, or dans ce cas on ne souhaite pas qu'il y ait de constructeur par défaut car on veut forcément qu'il y aie au moins en argument le nom du personnage

                  2)

                  On peut dans ce cas déclarer qu'un seul constructeur avec des valeurs par défaut sur les autres arguments si c'est à ça que tu penses, mais tu étais dans le même cas auparavant donc j'ai juste repris la même logique.
                  ça permet d'avoir des logiques un peu différente (par exemple dans le premier constructeur je crois qu'on a un pointeur null vers une arme alors que dans le deuxième on la construit) et aussi d’interdire le constructeur avec 2 arguments

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Dream on, Dream on, Dream until your dream comes true
                    22 octobre 2018 à 16:12:55

                    Mais si la fonction du specifier delete ne doit pas exister, autant ne pas l'écrire du tout, non ?

                    Et ok pour le petit 2 je laisse les deux constructeurs alors.

                    • Partager sur Facebook
                    • Partager sur Twitter

                    C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                      22 octobre 2018 à 16:24:41

                      Effectivement si on devait écrire toutes les fonctions qui n'existent pas, on serrait pas sorti de l'auberge xD

                      Mais là il s'agit d'un cas un peu particulier, c'est ce que j'essayais de dire. Le constructeur sans argument ( aka constructeur par défaut ), le constructeur par copie `MyClass(MyClass const & other)`, le constructeur par mouvement `MyClass(MyClass && other)`, les opérateurs d'affectations qui vont avec, et le destructeur sont automatiquement générés par le compilateur (si le contenu de la classe le permet) quand ils ne sont pas défini. Par conséquent, lorsqu'on ne les souhaite pas, il faut le préciser en spécifiant `=delete;`

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Dream on, Dream on, Dream until your dream comes true
                        22 octobre 2018 à 16:25:37

                        romantik a écrit:

                        Le specifier delete te permet de préciser que cette fonction ne doit pas exister, car le compilateur génère par défaut les constructeurs par défaut et par copie, or dans ce cas on ne souhaite pas qu'il y ait de constructeur par défaut car on veut forcément qu'il y aie au moins en argument le nom du personnage

                        Le constructeur par défaut est automatiquement supprimé puisque tu as déclaré des constructeurs à paramètres qui ne sont pas la copie/le move.

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                          22 octobre 2018 à 16:31:08

                          Du coup dans le Personnage.cpp, je me retrouve avec ça : 

                          Personnage::Personnage(std::string nomPersonnage) :
                          {
                              
                          }
                          
                          Personnage::Personnage(std::string nomPersonnage, string nomArme, int degatsArme) : m_vie(100), m_arme(nomArme, degatsArme)
                          {
                          
                          }

                          mais il faut que je mettes quoi (je suis un peu perdu...)

                          • Partager sur Facebook
                          • Partager sur Twitter

                          C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                            22 octobre 2018 à 16:40:14

                            Ksass`Peuk a écrit:

                            Le constructeur par défaut est automatiquement supprimé puisque tu as déclaré des constructeurs à paramètres qui ne sont pas la copie/le move.


                            Au temps pour moi, ça me parle maintenant que tu le dit, comme quoi ça fait jamais de mal de revoir les bases

                            RomainBricout a écrit:

                            il faut que je mettes quoi (je suis un peu perdu...)

                            C'est le même contenu qu'avant, tu vas juste rajouter l'initialisation de m_nom dans la liste d'initialisation

                            Personnage::Personnage(std::string nomPersonnage):
                                m_nom(nomPersonnage)
                            {
                              // Pareil que le ctor par défaut avant l'ajout du nom
                            }

                            Et tu définiras le nom dans la fonction appelante

                            int main(int, char**)
                            {
                                std::string nomHero;
                                std::cin >> nomHero; // TODO : saisie sécurisée
                            
                                Personnage hero(nomHero); // appel du premier constructeur
                                Personnage mechant("Voldemort", "Baguette de sureau", 50); // appel du second constructeur
                            
                                mechant.attaquer(hero);
                                // etc...
                            
                                return 0;
                            }





                            • Partager sur Facebook
                            • Partager sur Twitter
                            Dream on, Dream on, Dream until your dream comes true
                              22 octobre 2018 à 16:53:53

                              eeeuuuuhhh, salut, j'ai fait ce que tu m'as indiqué au niveau des constructeurs et ai ensuite demandé au méchant d'attaquer le héros une fois. Ensuite j'ai afficher leur état...

                              Tout est cohérent sauf la vie du méchant qui se retrouve propulsée à 4 636 600.

                              edit : je devrais peut être empêcher la vie de dépasser 100 :D

                              -
                              Edité par RomainBricout 22 octobre 2018 à 16:54:32

                              • Partager sur Facebook
                              • Partager sur Twitter

                              C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                                23 octobre 2018 à 11:25:31

                                Vu que tes constructeurs n'initialisent pas m_vie, m_vie vaut ce qu'il y a dans la mémoire à cet endroit là, c'est à dire n'importe quoi.

                                Tu peux initialiser par défaut:

                                #ifndef DEF_PERSONNAGE
                                #define DEF_PERSONNAGE
                                  
                                #include <iostream>
                                #include <string>
                                #include "Arme.h"
                                  
                                class Personnage
                                {
                                    public:
                                  
                                    Personnage() = delete;
                                    Personnage(std::string nomPersonnage);
                                    Personnage(std::string nomPersonnage, std::string nomArme, int degatsArme);
                                    void recevoirDegats(int nbDegats);
                                    void attaquer(Personnage &cible);
                                    void seSoigner(int quantiteSoin);
                                    void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
                                    bool estVivant() const;
                                    void afficherEtat() const;
                                 
                                    void renommer(std::string nouveau_nom);
                                  
                                    private:
                                  
                                    int m_vie{100}; // Si je ne précise rien dans le constructeur m_vie vaudra 100
                                    /*int m_vie{};  // Là m_vie vaudra la valeur d'initialisation par défaut pour un int c'est à dire 0.*/
                                    Arme m_arme;
                                    std::string m_nom;
                                };
                                  
                                #endif

                                Ou bien initialiser dans le constructeur (il est fait pour ça)

                                Personnage::Personnage(std::string nomPersonnage)
                                    :m_vie{100}
                                    ,m_nom{nomPersonnage}
                                {
                                  // Pareil que le ctor par défaut avant l'ajout du nom
                                }




                                -
                                Edité par int21h 23 octobre 2018 à 11:25:53

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                                  23 octobre 2018 à 22:49:42

                                  Salut, je ne savais pas qu'on pouvait initialiser un attribut par défaut à l'aide des {} mais merci du tuyau. Mais du coup, si je veux le faire dans le constructeur, il faut que je le fasse dans tous les constructeurs pour que l'attribut soit tout de même initialisé si j'utilise pas le constructeur par défaut ?

                                  Au fait, c'est quoi le ctor, ça fait plusieurs fois que je te vois le citer mais je ne sais pas ce que c'est...?

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                                    24 octobre 2018 à 0:14:39

                                    RomainBricout a écrit:

                                    je ne savais pas qu'on pouvait initialiser un attribut par défaut à l'aide des {} mais merci du tuyau.

                                    Il y a plusieurs moyens d'initialiser des valeurs (plus de détails), la syntaxe avec les accolades est à privilégier car elle unifie la manière d'initialiser entre les types, mais il faut prendre garde car sa signification dépend du contexte, ce n'est pas forcément un appel au constructeur

                                    Et plus particulièrement pour des variables membres ...

                                    RomainBricout a écrit:

                                    il faut que je le fasse dans tous les constructeurs pour que l'attribut soit tout de même initialisé si j'utilise pas le constructeur par défaut ?

                                    Oui pour les listes d'initialisation, c'est pour ça que l'initialisation par défaut dans la définition de la classe est pratique, elle permet de ne pas te répéter pour chaque constructeur et ne spécifier que ce qui a besoin de l'être

                                    RomainBricout a écrit:

                                    Au fait, c'est quoi le ctor, ça fait plusieurs fois que je te vois le citer mais je ne sais pas ce que c'est...?

                                    C'est simplement une abréviation de constructor, tu trouveras aussi dtor pour destructor

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Dream on, Dream on, Dream until your dream comes true
                                      24 octobre 2018 à 0:56:37

                                      1) ok merci pour l'info !

                                      2) donc vaut mieux toujours initialiser les attributs dans le prototype de la classe et changer seulement les trucs à changer dans le ctor :D

                                      3) EHEH je suis bête... c'est tellement logique... :lol:

                                      -
                                      Edité par RomainBricout 24 octobre 2018 à 0:56:56

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      C++ à la vie à la mort. (Le python c'est bien aussi) || Rejoignez : https://discord.gg/9r3zqgg

                                      Problème classe personnage

                                      × 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