Partage
  • Partager sur Facebook
  • Partager sur Twitter

Argument par defaut dans un constructeur de class

Sujet résolu
    21 septembre 2018 à 11:54:52

    Hello World!~

    Mmh~ je sent que je vais en passer du temps sur ce forum... oups pardon j' était perdu dans mes pensées :-° BREF

    Je cherche a créer une class Fraction et j'ai quelque problème lors de la compilation (ça compile pas). Je souhaiterai faire en sorte que mon constructeur, lorsque je ne met aucun argument lors de mon initialisation de variable (ci-dessous), mette ma variable tout seul a 0/1 (donc valeurs d'argument par défaut) et dans le cas contraire qu'il utilise les valeurs entrées par l'utilisateur.

    #include <iostream>
    #include "Fraction.h"
    
    const int END = 0;
    
    int main()
    {
        Fraction f1;
        Fraction f2(2);
        Fraction f3(2, 4);
        f1.show();
        return (END);
    }

    On devrait donc avoir f1 = 0/1, f2 = 2/1 et f3 = 2/4 (dans un premier temps...).

    Voici ma class:

    #pragma once
    
    class Fraction
    {
        public:
            Fraction(int x = 0, int y = 1);
            void show() const;
        private:
            int mX;
            int mY;
    };
    

    Mes methods:

    #include <iostream>
    #include "Fraction.h"
    
    using std::cout;
    using std::endl;
    
    Fraction::Fraction(int x = 0, int y = 1) : mX(x), mY(y)
    {
    }
    
    void Fraction::show() const
    {
        cout << mX << "/" << mY << endl;
    }
    

    Et mes erreures de compilation:

    Erreurs de compilation

    Merci d'avance pour votre aide! :ange:

    PS: Je sais le cours de C++ d'OC est très mauvais, je devrais plutôt suivre celui de Guillaume Belz ce que je fais en parallèles... Je veux voir ce que je devrais faire contre ce que je ne dois surtout pas faire eeeet~ ça fais plus d'exo.

    PS: Si vous voyez une critique a faire sur mon code (manière de coder), allez y, j'essaye de coder le plus propre possible~

    EDIT--

    Au final j'ai trouver avec un peu d'aide extérieure; désole pour le post inutile...

    Pour ceux qui passe par le même problème, il suffit juste de laisser les arguments "basiques" dans le prototype du constructeur dans le fichier .cpp comme cela:

    class Fraction
    {
        public:
            Fraction(int x = 0, int y = 1);
            void show() const;
        private:
            int mX;
            int mY;
    };
    Fraction::Fraction(int x, int y) : mX(x), mY(y)
    {
    }

    Voila, et ça devrais compiler et marcher comme voulus! Moi ça marche en tout cas...


    PS: Vous pouvez comme même m'envoyer vos commentaires de code :-°

    -
    Edité par Rymfire 21 septembre 2018 à 12:30:37

    • Partager sur Facebook
    • Partager sur Twitter
    Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.
      21 septembre 2018 à 13:10:32

      Hello,

      Juste une chose,  ça ne me semble pas terrible de faire ça c'est ambigu je trouve, d'ailleurs le compilo' le dit aussi si tu ajoutes un constructeur par défaut.

      À partir du moment où on est censé pouvoir instancier une classe sans paramètre, il devrait y avoir un constructeur par défaut avec une initialisation directe des variables dans la classe elle-même, ce qui a en plus l'avantage de ne pas être contraint d'initialiser à chaque fois les variables non précisées à la construction dans la liste d'initialisation :

      class Fraction
      {
      public:
          Fraction() = default;
          Fraction(int x) : mX{x} {}
          Fraction(int x, int y) : mX{x}, mY{y} {}
      
          void show() const;
      
      private:
          int mX{0};
          int mY{1};
      };
      int main()
      {
          Fraction f1{};     // 0/1
          Fraction f2{2};    // 2/1
          Fraction f3{2, 2}; // 2/2
      
          return 0;
      }

      Et prend l'habitude d'initialiser les variables avec les accolades. C'est plus sûr.

      int i;
      ++i; // 4200348 : Undefined behavior
      
      int j{};
      ++j; // 1 : Ok
      
      float k{1.5f};
      int k2(k); // Le compilateur ne dit rien...
      int k3{k}; // Warning du compilateur en indiquant une "narrowing conversion"
      

      Et si tu veux en savoir plus sur le sujet : https://zestedesavoir.com/forums/sujet/5876/debuter-en-c/#p107110

      -
      Edité par Guit0Xx 21 septembre 2018 à 13:14:35

      • Partager sur Facebook
      • Partager sur Twitter

      ...

        23 septembre 2018 à 11:40:41

        Guit0Xx a écrit:

        class Fraction
        {
        public:
            Fraction() = default;
            Fraction(int x) : mX{x} {}
            Fraction(int x, int y) : mX{x}, mY{y} {}
        
            void show() const;
        
        private:
            int mX{0};
            int mY{1};
        };


        Salut, merci pour ton commentaire d'abord. En ce qui concerne le code, je vais m'y atteler de suite!

        Le mot-clé `default;` signifie que le constructeur appelé par défaut est celui sur la même ligne?

        Je ne savais pas qu'on pouvais initialiser les valeurs de mX et mY directement dans la class ou alors es-ce les valeurs par défaut qui sont introduite? Cela marche t'il seulement avec les accolades? 

        Guit0Xx a écrit:

        Et prend l'habitude d'initialiser les variables avec les accolades. C'est plus sûr.

        int i;
        ++i; // 4200348 : Undefined behavior
        
        int j{};
        ++j; // 1 : Ok
        
        float k{1.5f};
        int k2(k); // Le compilateur ne dit rien...
        int k3{k}; // Warning du compilateur en indiquant une "narrowing conversion"
        
        J'aimerai bien mais mon compilateur ne semble pas vouloir le compiler... je vais peut être essayer avec g++ mais je n'ai pas accès au pc avec celui-ci pour le moment. Je vais voir ton link :-°

        -
        Edité par Rymfire 23 septembre 2018 à 11:42:17

        • Partager sur Facebook
        • Partager sur Twitter
        Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.
          23 septembre 2018 à 13:59:58

          Guit0Xx a écrit:

          Le mot-clé `default;` signifie que le constructeur appelé par défaut est celui sur la même ligne?

          Non, il indique qu'il n'y rien a de spécial et que le compilateur peut créer à ta place le constructeur de la ligne (ici c'est le constructeur par défaut.)

          Guit0Xx a écrit:

          Je ne savais pas qu'on pouvais initialiser les valeurs de mX et mY directement dans la class ou alors es-ce les valeurs par défaut qui sont introduite? Cela marche t'il seulement avec les accolades?

          Les accolades sont utilisables depuis 2011 (le C++11 ou C++0x), le égal est aussi possible mais pour un meilleur contrôle il faut préférer les accolades.
          Cette expression permet d'indiquer ce qui sera fait pour les membres qui ne sont pas explicitement initialisés dans chacun des constructeurs, donc le constructeur par défaut dans ton cas exemple.

          Guit0Xx a écrit:

          J'aimerai bien mais mon compilateur ne semble pas vouloir le compiler... je vais peut être essayer avec g++ mais je n'ai pas accès au pc avec celui-ci pour le moment. Je vais voir ton link :-°

          Indique nous l'erreur que tu reçois. Ton compilateur doit être d'avant 2011 ou sinon c'est que la fonctionnalité C++11 n'est pas activée (et le message d'erreur devrait d'indiquer quoi faire.)

          • Partager sur Facebook
          • Partager sur Twitter

          En recherche d'emploi.

            23 septembre 2018 à 17:13:12

            Dalfab a écrit:

            Guit0Xx a écrit:

            Ba alors, on a pas les yeux en face des trous ? :D

            • Partager sur Facebook
            • Partager sur Twitter

            ...

              23 septembre 2018 à 18:09:02

              Salut,

              Pour répondre à ta question de base:

              Les valeurs par défaut ne doivent être fournie que dans la déclaration des fonctions, l'implémentation des fonctions, quand elle est séparée (comme c'est le cas ici) ne doit pas contenir ces valeurs.

              Pour aller plus loin:

              Il faut être particulièrement prudent lorsque l'on décide de préciser une (ou pire, des) valeur(s) par défaut pour les paramètres d'une fonction.

              Il y a deux raisons majeures à cette prudence:

              La première est que chaque valeur par défaut ajoute un prototype possible pour la fonction, et qu'on peut donc "assez facilement" créer des conflits.  Je m'explique:

              Mettons que nous déclarions une fonction proche de

              void foo(int i = 0,  int j = 0, int k = 0);

              Les trois valeurs par défaut nous permettent d'appeler foo de quatre manière différentes, à savoir

              • foo() qui utilise les trois valeurs par défaut  (i == 0, j == 0, k == 0)
              • foo(1) qui associe la valeur 1 à  i, et les valeurs par défaut pour j et k
              • foo(1,2) qui associe la valeur 1 à  i, la valeur 2 à j et la valeur par défaut pour k
              • foo(1,2,3) qui associe la valeur 1 à  i, la valeur 2 à j et la valeur 3 à k

              Si "je suis distrait", et que j'essaye de créer, à coté de cette fonction, une autre fonction foo "surchargée" proche de

              void foo(int i,  int j, int k);

              Le prototype de cette fonction utilisera le même nombre de paramètres de même type que la quatrième possibilité offerte par les paramètres par défaut, et cela occasionnera un conflit, le compilateur ne sachant pas -- lors de l'appel à foo(1, 2, 3) s'il doit faire appel à la "version" qui dispose de valeurs par défaut ou à la version qui n'en a pas.

              En un mot: le nombre et / ou le type des paramètres de chaque surcharge de fonction doit être strictement unique. Par exemple, une fonction proche de

              void foo(int i, int j, float k)

              serait elle tout à fait acceptée car nécessite également trois paramètre, mais il y a un type qui est différent de tous les autres prototypes ;)

              La deuxième raison découle directement de la première, mais est beaucoup plus subtile: il faut s'assurer que chaque prototype offert par la présence des valeurs par défaut soit cohérent et sensé.  Je m'explique:

              Il faut, pour chaque prototype autorisé par les valeurs par défaut, se poser la question de savoir si il y a du sens à permettre à la fonction avec les paramètres en question.

              Comme nous sommes, dans le cas présent, occupés à travailler sur le constructeur, nous devons donc nous poser la question

              1. Y a-t-il du sens à permettre la création d'une donnée de type fraction sans aucune valeur?
              2. Y a-t-il du sens à permettre la création d'une donnée de type fraction avec une seule valeur?
              3. Y a-t-il du sens à permettre la création d'une donnée de type fraction avec deux valeurs?

              la réponse au (3) est sans équivoque : bien sur qu'il y a du sens à permettre la création d'une fraction sous la forme de

              fraction f{2/3};

              La réponse au (2) est déjà "beaucoup moins claire", car, s'il y a effectivement du sens à permettre la création d'une fraction sous la forme de

              Fraction f{5}; // f == 5/1

              il faut se poser la question de savoir "Mais en aurons nous besoin?". Et la réponse à cette question n'est pas forcément "oui"!!!

              Bien sur, dans l'immédiat, tu fais juste des essais pour essayer de comprendre le principe, et tu serais donc sûrement tenté de répondre oui à cette question. Mais, essaye de "voir un peu plus loin" que ton essais actuel, et de réfléchir à un programme qui devrait utiliser ta classe Fraction, et, surtout, à la manière dont ce programme créera les différentes données de type fraction.

              S'il s'agit d'une programme qui crée les fractions sous une forme qui pourrait être proche de

              int main(){
                  for(int numerator = 0; numerator<10; ++numerator){
                      for(denominator = 1; denominator<11; ++denominator{
                          Fraction f{numerator, denominator};
                          /* on utilise f ici */
                      }
                  }
                  return 0;
              }

              La réponse est clairement "non" : on n'a absolument pas besoin de pouvoir créer une fraction en ne fournissant que le numérateur.

              Et même si le programme en question venait à demander à l'utilisateur d'introduire les valeurs pour chaque fraction créée ou à lire ces valeurs dans un flux quelconque, on devrait s'attendre à ce qu'il demande (ou extraie du flux) à chaque fois ... la valeur du numérateur et du dénominateur.

              Si bien que la réponse resterait clairement "non".

              Et les choses sont encore plus subtiles pour le (1), car, le principe de base est de s'assurer que les données que l'on crée soient cohérentes et sensées dés le moment de leur création.

              Or, ta classe Fraction représente une valeur. Il faut donc que la valeur représentée par une fraction "créée par défaut" soit ... cohérente et sensée.

              Pour répondre à la question de savoir s'il est sensé de permettre la création d'une fraction sans fournir aucune valeur, il faut d'abord et avant tout... déterminer quelle valeur peut être utile comme valeur par défaut cohérente et sensée :p

              • Est-ce 0/1 ( == 0) ?
              • Est-ce 1/1 ( == 1 ) ?
              • Est-ce 0/0 (valeur indéfinie, qui provoquera une erreur à l'exécution si on essaye de l'évaluer) ?
              • Est-ce "une autre valeur arbitraire" (et surtout laquelle)?

              Et, une fois que nous aurons déterminé cette valeur par défaut (afin de répondre à la question "est-il sensé de permettre la création d'une fraction de cette manière?", il faudra encore répondre à la question "Mais en aurons nous besoin?".

              Et, pour répondre à cette question, nous devrons répondre à une autre question beaucoup plus vaste qui est

              Quel usage va-t-on faire de nos fractions?

              Ou, pour être plus précis encore :

              La manière dont on va utiliser nos fractions implique-t-elle -- ne serait-ce que dans quelques situations très particulière -- d'utiliser la valeur par défaut ?

              Et, malheureusement, la réponse à cette question est très loin d'être claire:  Même le fait d'envisager l'utilisation de collections de fractions comme std::vector<Fraction>, comme std::map<float, Fraction> ou comme std::array<Fraction, NombreDeFractions> ne permet pas de donner de réponse précise.

              Car, si tu décide de ne pas fournir la possibilité de créer une fraction avec "une valeur par défaut", tu imposeras "une manière de travailler" avec de telles collections, et cela peut être une excellente chose parce que cette manière de travailler sera "plus sécurisante" ... ou non.

              Par contre, si tu décide de fournir cette possibilité, tu autoriseras certaines manière de travailler, et, encore une fois, cela peut être une excellente chose ... ou non.

              Car, le problème à ce moment là, c'est que les manières de travailler que tu autoriseras peuvent très facilement provoquer des catastrophes (surtout si tu choisi 0/0 comme valeur par défaut).  Or, si je devais abandonner les principes SOLID au profit d'un seul conseil à donner, je choisirais de donner le conseil de Scott Meyers dont la traduction est

              Rendez vos interface faciles à utiliser correctement et difficile à utiliser de manière incorrecte

              En autorisant l'utilisation de valeurs par défaut, tu rend surtout ta classe ... beaucoup plus facile à utiliser de manière incorrecte.

              Personnellement, je choisirais très certainement de rendre ma classe "plus difficile" à utiliser de manière incorrecte.  Et toi?

              • Partager sur Facebook
              • Partager sur Twitter
              Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                24 septembre 2018 à 13:23:29

                Guit0Xx a écrit:

                À partir du moment où on est censé pouvoir instancier une classe sans paramètre, il devrait y avoir un constructeur par défaut avec une initialisation directe des variables dans la classe elle-même, ce qui a en plus l'avantage de ne pas être contraint d'initialiser à chaque fois les variables non précisées à la construction dans la liste d'initialisation :

                Pas d'accord. C'est écrire 3 lignes pour faire la même chose qu'une seule. La version intiale me convient.

                class Fraction
                {
                public:
                    Fraction(int x = 0, int y = 1) : mX{x}, mY{y} {}
                 
                    void show() const;
                 
                private:
                    int mX{0};
                    int mY{1};
                };

                (Il peut y avoir une discussion sur les valeurs par défaut et où les mettre. Mais cela ne justifie pas d'ecrire 3 constructeurs au lieu d'un).

                Et si on a besoin de plusieurs constructeurs, il sera souvent pertinent d'utiliser les delegating constructors (les constructeurs qui vont appeler un autre constructeur) pour avoir moins de code a écrire, tout en garantissant les comportement par defaut.

                Par exemple :

                class Fraction
                {
                public:
                    Fraction() : Fraction(0, 1) {}
                    Fraction(int x) : Fraction(x, 1) {}
                    Fraction(int x, int y) : mX{x}, mY{y} { do_someting(); }
                 
                    void show() const;
                 
                private:
                    int mX{0};
                    int mY{1};
                }; 

                koala01 a écrit:

                Si "je suis distrait", et que j'essaye de créer, à coté de cette fonction, une autre fonction foo 

                Ce n'est pas très pertinent comme "distraction". Le compilateur produit une erreur et tu es obligé de corriger. Il n'y a pas de risque d'ecrire un code invalide.

                koala01 a écrit:

                En un mot: le nombre et / ou le type des paramètres de chaque surcharge de fonction doit être strictement unique. Par exemple, une fonction proche de

                Paradoxalement, cette signature me pose plus de problème. Parce qu'il est facile de se tromper dans le code, d'appeler le mauvais constructeur et d'avoir un comportement qui n'est pas celui qu'on attend, sans que ce problème soit très evident a voir.

                (Je parle du cas où le seule changement entre 2 signatures serait entre un int vs un float)

                foo(1,2,3.); // facile de louper le point

                A mon sens : il ne devrait pas y avoir des telles surcharges. Préférer utiliser des noms différents ou avoir des paramètres assez differents pour ne pas avoir d'ambiguité.

                -
                Edité par gbdivers 24 septembre 2018 à 13:51:15

                • Partager sur Facebook
                • Partager sur Twitter
                  24 septembre 2018 à 17:49:41

                  gbdivers a écrit:

                  Ce n'est pas très pertinent comme "distraction". Le compilateur produit une erreur et tu es obligé de corriger. Il n'y a pas de risque d'ecrire un code invalide.

                  Nous sommes bien d'accord là dessus : le compilateur t'insultera parce que tu fais "quelque chose d'invalide".

                  Mais, reviens dix ans en arrière, à l'époque où tu avais toutes les peines du monde à comprendre ce que le compilateur te disait

                  Ou penses peut-être à une situation plus récente qui aurait pu t'arriver suite à cette distraction, et dans laquelle tu auras passé "un certain temps" à te "gratter la tête" en te demandant "mais qu'est ce qu'il veut me dire cet emm**eur".

                  j'admets volontiers qu'une code aussi trivial que

                  void foo(int i = 0, int j = 0, int k = 0 ){
                  	
                  }
                  void foo(int i , int j, int k){
                  	
                  }

                  provoquera une sortie "relativement compréhensible" du genre de

                   g++ main.cpp 
                  main.cpp:5:6: error: redefinition of ‘void foo(int, int, int)’
                   void foo(int i , int j, int k){
                        ^~~
                  main.cpp:2:6: note: ‘void foo(int, int, int)’ previously defined here
                   void foo(int i = 0, int j = 0, int k = 0 ){
                  

                  Mais ce n'est pas toujours aussi clair!

                  Quoi, tu ne t'es jamais gratté la tête face à un tel message??? :D:p


                  • Partager sur Facebook
                  • Partager sur Twitter
                  Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                    24 septembre 2018 à 18:05:54

                    koala01 a écrit:

                    reviens dix ans en arrière

                    Pourquoi je ferais cela ?

                    (Ou plutot, si j'avais le pouvoir de faire cela, ça ne serait pas pour faire du C++)

                    • Partager sur Facebook
                    • Partager sur Twitter
                      24 septembre 2018 à 18:12:28

                      Je voulais dire : "rappelle toi le (pas si) bon vieux temps (que cela)" :D
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                        26 septembre 2018 à 11:21:40

                        Desole, j'ai pas trop eu le temps de coder depuis, je regarde vos messages ce soir :waw:
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.
                          28 septembre 2018 à 16:03:15

                          Dalfab a écrit:

                          Guit0Xx a écrit:

                          J'aimerai bien mais mon compilateur ne semble pas vouloir le compiler... je vais peut être essayer avec g++ mais je n'ai pas accès au pc avec celui-ci pour le moment. Je vais voir ton link :-°

                          Indique nous l'erreur que tu reçois. Ton compilateur doit être d'avant 2011 ou sinon c'est que la fonctionnalité C++11 n'est pas activée (et le message d'erreur devrait d'indiquer quoi faire.)


                          Voici l’erreur de compilation que je reçois:

                          Erreurs de compilation

                          Mais il faut savoir que je code avec 2 pc parce que l'un est sous windows et l'autre sous linux (l'erreur si dessus viens de windows). Je n'ai jamais essayer sous linux.

                          koala01 a écrit:

                          Car, le problème à ce moment là, c'est que les manières de travailler que tu autoriseras peuvent très facilement provoquer des catastrophes (surtout si tu choisi 0/0 comme valeur par défaut).  Or, si je devais abandonner les principes SOLID au profit d'un seul conseil à donner, je choisirais de donner le conseil de Scott Meyers dont la traduction est

                          Rendez vos interface faciles à utiliser correctement et difficile à utiliser de manière incorrecte

                          En autorisant l'utilisation de valeurs par défaut, tu rend surtout ta classe ... beaucoup plus facile à utiliser de manière incorrecte.

                          Personnellement, je choisirais très certainement de rendre ma classe "plus difficile" à utiliser de manière incorrecte.  Et toi?

                          Pour ce projet, je m’entraîne donc je vais continuer a le faire de la manière dites au dessus. Car, on le sait bien, en programmation, c'est en codant qu'on apprend a faire. CEPENDANT, je retiens ta réflexion car effectivement, dans un futur projet il serai probablement utile de penser a la manière d'utiliser la classe que je construit. Je choisirai très probablement "Facile a utiliser, difficile a maîtriser" je pense... ;)

                          gbdivers a écrit:

                          Pas d'accord. C'est écrire 3 lignes pour faire la même chose qu'une seule. La version intiale me convient.

                          class Fraction
                          {
                          public:
                              Fraction(int x = 0, int y = 1) : mX{x}, mY{y} {}
                           
                              void show() const;
                           
                          private:
                              int mX{0};
                              int mY{1};
                          };

                          (Il peut y avoir une discussion sur les valeurs par défaut et où les mettre. Mais cela ne justifie pas d'ecrire 3 constructeurs au lieu d'un).

                          Et si on a besoin de plusieurs constructeurs, il sera souvent pertinent d'utiliser les delegating constructors (les constructeurs qui vont appeler un autre constructeur) pour avoir moins de code a écrire, tout en garantissant les comportement par defaut.

                          Par exemple :

                          class Fraction
                          {
                          public:
                              Fraction() : Fraction(0, 1) {}
                              Fraction(int x) : Fraction(x, 1) {}
                              Fraction(int x, int y) : mX{x}, mY{y} { do_someting(); }
                           
                              void show() const;
                           
                          

                          Mais du coup je dois utiliser quelle méthode (pour être le plus propre possible)?

                          Et aussi je vois que vous faites tous cela:

                              private:
                                  int mX{0};
                                  int mY{1};


                          En fesant cela vous fetes quoi? vous initialez la valeur a 0 et 1 ou ce sont les valeurs par defaut... J'avais cru comprendre qu'on ne devrais jamais initialiser des variables dans la declaration de la classe...

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.
                            28 septembre 2018 à 16:49:39

                            Rymfire a écrit:

                            Voici l’erreur de compilation que je reçois:

                            Ton erreur ne correspond pas aux codes que tu as donné avant. C'est dans la fonction main que tu as une erreur. A priori, tu declares 2 fois la meme variable f4.

                            Rymfire a écrit:

                            En fesant cela vous fetes quoi? vous initialez la valeur a 0 et 1 ou ce sont les valeurs par defaut... J'avais cru comprendre qu'on ne devrais jamais initialiser des variables dans la declaration de la classe...

                            Tu dois toujours declarer tes variables dans la classe. Et oui, c'est une initialisation par defaut.

                            Rymfire a écrit:

                            Mais du coup je dois utiliser quelle méthode (pour être le plus propre possible)?

                            1 seul constructeur.
                            class Fraction
                            {
                            public:
                                Fraction(int x = 0, int y = 1) : mX{x}, mY{y} {}
                              
                                void show() const;
                              
                            private:
                                int mX{0};
                                int mY{1};
                            };
                            • Partager sur Facebook
                            • Partager sur Twitter
                              1 octobre 2018 à 10:40:16

                              gbdivers a écrit:

                              Rymfire a écrit:

                              Voici l’erreur de compilation que je reçois:

                              Ton erreur ne correspond pas aux codes que tu as donné avant. C'est dans la fonction main que tu as une erreur. A priori, tu declares 2 fois la meme variable f4.

                               C'est bon j'ai regle le probleme! Merci

                              gbdivers a écrit:

                              Rymfire a écrit:

                              En fesant cela vous fetes quoi? vous initialez la valeur a 0 et 1 ou ce sont les valeurs par defaut... J'avais cru comprendre qu'on ne devrais jamais initialiser des variables dans la declaration de la classe...

                              Tu dois toujours declarer tes variables dans la classe. Et oui, c'est une initialisation par defaut.

                              Rymfire a écrit:

                              Mais du coup je dois utiliser quelle méthode (pour être le plus propre possible)?

                              1 seul constructeur.

                              class Fraction
                              {
                              public:
                                  Fraction(int x = 0, int y = 1) : mX{x}, mY{y} {}
                                
                                  void show() const;
                                
                              private:
                                  int mX{0};
                                  int mY{1};
                              };


                              Ok je vois, je prend note!

                              Mais du coup si le programme sait que mX{0} et mY{1} par defaut, il y a t il vraiment besoin de redefinir ces limites dans la declaration du constructeur?

                              -
                              Edité par Rymfire 1 octobre 2018 à 10:43:10

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.
                                1 octobre 2018 à 10:46:01

                                Oui, sinon aucun constructeur sans paramètre ne peut être utilisé. Le compilateur ne sait pas a priori que les paramètres que tu transmets en entrée du constructeur vont servir à directement instancier les valeur internes de ta classe.

                                • Partager sur Facebook
                                • Partager sur Twitter

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

                                  1 octobre 2018 à 11:01:41

                                  Rymfire a écrit:

                                  Mais du coup si le programme sait que mX{0} et mY{1} par defaut, il y a t il vraiment besoin de redefinir ces limites dans la declaration du constructeur?

                                  Ce sont les valeurs par défaut qui pourraient servir si il y avait d'autres constructeurs. "Avoir vraiment besoin", dans le cadre d'un exemple bidon, c'est assez relatif.

                                  Déjà, il est assez probable que la Fraction garde son numérateur et son dénominateur sous forme normalisée : dénominateur positif, numérateur et dénominateurs premiers entre eux. C-a-d que si on définit

                                  Fraction f { 2, -4};
                                  

                                  ce qui sera stocké c'est  -1 et 2.


                                  -
                                  Edité par michelbillaud 1 octobre 2018 à 11:05:37

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    2 octobre 2018 à 10:12:03

                                    michelbillaud a écrit:

                                    Fraction f { 2, -4};
                                    

                                    ce qui sera stocké c'est  -1 et 2.


                                    Tien tu viens de me faire penser que j'ai pas gérer ce détails la o.0

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.

                                    Argument par defaut dans un constructeur de class

                                    × 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