Partage
  • Partager sur Facebook
  • Partager sur Twitter

Petite question concernant l'utilisation de this

    28 mai 2016 à 11:10:53

    Bonjour ! 

    J'ai une petite question, j'aimerais qu'une de mes classes se passe elle même en pointeur pour "s'inscrire dans une autre" et en gros je passe par le constructeur un paramètre et j'ai ça :

    ConnexionMenu test(this, windowEventManager);

    J'ai ensuite des problèmes incompréhensibles avec l'utilisation de mon code, j'aimerais donc savoir si le problème vient du "this".

    Si oui pourriez-vous m'expliquer pourquoi ? Et quelle solution je pourrais utiliser ? 

    Si non je vous enverrais le reste du code si vous voulez bien m'aider :) 

    Merci d'avance pour vos réponses, je reste à disposition et si vous avez une idée ou une piste n'hésitez pas :) 
     

    • Partager sur Facebook
    • Partager sur Twitter
      28 mai 2016 à 11:49:36

      this, est un pointeur qui représente l'objet courrant (ou la classe elle-même), il est definit automatiquement, il est utile entre autre lors de la surcharge d'operateurs d'affectation, peut être utilisé pour lever certaines ambiguités ect ect .....

      Par exemple considère le code suivant:

      class bidon
      {
      public:
          myClass(): compteur{0};
          void setStart(int const compteur);
      private:
          int compteur;
      };

      On a une fonction membre dont le nom du paramètre est identique au nom de l'une des variables membre.
      Le pointeur this est alors utile pour différencier les deux:

      void bidon::setStart(int const compteur)
      {
          this->compteur = compteur;
      }



      • Partager sur Facebook
      • Partager sur Twitter
        28 mai 2016 à 12:05:28

        D'accord, mais il ne sert que à ça ? Et concernant l'utilisation que j'en ai faite ? Car lors de l'utilisation de la variable que j'ai initialiser avec le this le programme plante comme si le pointeur n'existait pas.

        Merci pour ta réponse :)

        • Partager sur Facebook
        • Partager sur Twitter
          28 mai 2016 à 12:07:36

          Spongebobcarre a écrit:

          Bonjour ! 

          J'ai une petite question, j'aimerais qu'une de mes classes se passe elle même en pointeur pour "s'inscrire dans une autre" et en gros je passe par le constructeur un paramètre et j'ai ça :

          ConnexionMenu test(this, windowEventManager);

          J'ai ensuite des problèmes incompréhensibles avec l'utilisation de mon code, j'aimerais donc savoir si le problème vient du "this".

          Si oui pourriez-vous m'expliquer pourquoi ? Et quelle solution je pourrais utiliser ? 

          Si non je vous enverrais le reste du code si vous voulez bien m'aider :) 

          Merci d'avance pour vos réponses, je reste à disposition et si vous avez une idée ou une piste n'hésitez pas :) 
           


          Il est clair qu'on ne peut pas trouver une explication, et encore moins une correction, pour des problèmes "incompréhensibles" non décrits, sur du code invisible.

          A part ça il n'y a pas de "pointeurs sur des classes", parce que les classes ne sont pas des données présentes en mémoire, en C++. Donc pas d'adresse, pas de pointeur.

          Ceci dit, passer this en paramètre, c'est tout à fait courant.

          -
          Edité par michelbillaud 28 mai 2016 à 12:09:42

          • Partager sur Facebook
          • Partager sur Twitter
            28 mai 2016 à 21:35:37

            @michelbillaud:
            Oui, dans l'absolu il n'y a pas de pointeur sur des classes, seulement sur des objets instanciés. Cependant, si l'OP demande l'utilité de ce pointeur, je pense qu'il debute, donc j'essaie d'employer un vocabulaire simpliste.

            @Spongebobcarre:
            Non, le pointeur this n'est pas utilisé seulement dans ces cas, il est utilisé partout ou tu as besoin de connaître l'objet courrant, ou le donner en paramètre, cela dépend de ce que tu veux faire.

            D'autres exemples qui me viennent à l'esprit:
            Liste chainées, arbres, relations parent / enfant ect ect ........ (liste non exhaustive).

            • Partager sur Facebook
            • Partager sur Twitter
              28 mai 2016 à 21:57:18

              Une utilisation fréquente est si on veut des fonctions membres "chainables", c'est à dire qu'au lieu d'écrire

              Robot r;
              r.avancer(10);
              r.gauche();
              r.avancer(20);
              r.droite();

              on écrive

              Robot r;
              
              r.avancer(10)
               .gauche()
               .avancer(20)
               .droite();

              à ce moment là il faut que chaque opération retourne l'objet robot modifié. Ca veut dire que la fonction membre retourne une référence

              class Robot 
              {
              
              ....
              
              Robot & gauche();
              ....
              }
              Robot & Robot::gauche() 
              {
                 ....
                 return *this;                  // ------------
              }

              Là ça parait rigolo mais décoratif, il se trouve que parfois c'est très utile. Par exemple << est chainable pour les opérations de sortie

              cout << "truc" 
                   << 12 
                   << "machine" 
                   << endl;


              PS : il faut expliquer de façon simple, mais pas laisser croire des trucs faux : il n'y a rien qui ressemble à des pointeurs sur des classes. Les débutants ont déjà assez de conceptions fausses sans en rajouter. Dans la phrase "une classe qui se passe elle même en pointeur pour s'inscrire dans une autre", tu peux imaginer....

              Ca doit être "un objet qui transmet son adresse qui est notée par un autre, d'une autre classe".

              Du genre

              class Equipe {
                set<Joueur *> membres;
              
                void ajouter(Joueur *p) {
                  membres.add(p);
                }
              };
              
              
              class Joueur {
                string nom;
                Equipe * equipe;
              
              public:
                Joueur(string n, Equipe * e)
                   : nom{n}
                   , Equipe{e}
                {
                   e->ajouter(this);         // ---------------
                }
              };
              






              -
              Edité par michelbillaud 28 mai 2016 à 22:11:24

              • Partager sur Facebook
              • Partager sur Twitter
                29 mai 2016 à 0:18:15

                Dans la liste d'initialisation, this a une valeur inconnue.
                • Partager sur Facebook
                • Partager sur Twitter
                  29 mai 2016 à 0:37:31

                  Dans la liste d'initialisation, this a une valeur inconnue.

                  Ce qui veux dire ? Qu'Il ne faudrait pas l'utiliser ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    29 mai 2016 à 7:45:28

                    Il faut l'utiliser avec précaution. Là c'est dans le corps du constructeur.

                    Ca poserait un problème si on dérivait une classe J2 de Joueur (et qu'on fasse du pôlymorphisme). A ce moment là son constructeur appellerait celui de Joueur, avant d'exécuter son propre corps. Et la fonction ajouter recevrait comme paramètre un pointeur vers une instance de J2 pas encore complètement initialisée. Donc en général il vaut mieux y faire attention

                    Mais là on est supposé savoir que ajouter(..) ne fait que noter une adresse, et ne déréférence pas le pointeur transmis; et on n'a pas de classe dérivée, etc. donc ça roule.

                    -
                    Edité par michelbillaud 29 mai 2016 à 9:29:12

                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 mai 2016 à 10:48:55

                      Personne ne tique sur l'utilisation d'un pointeur nu dans les paramètres d'un constructeur ???

                      C'est généralement assez archaïque d'utiliser un pointeur nu comme l'est this.

                      L'objet "test" de type "ConnectionMenu" reçoit un pointeur, nu, donc, on ne sait pas s'il peut être null ou pas (paramètre optionnel ?), si cet objet "test" prend en charge la "propriété de l'objet" (si c'est à lui d'appeler le destructeur de l'objet passé en paramètre), etc...

                      C'est toutes ces choses inconnues qui font que l'utilisation de pointeurs nus ne devrait pas être abordée avant bien des notions plus fondamentales.

                      Un cas habituel d'emmerdes avec les pointeurs "this" passé en paramètre, c'est que l'objet qui le reçoit fait très souvent l'assertion que l'objet pointé par "this" sera valide aussi longtemps que l'objet qui le reçoit.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        30 mai 2016 à 11:26:30

                        Si tu arrives à écrire un texte qui explique, à des débutants en C++ qui ne savent pas encore ce qu'est un pointeur,une adresse, une déréférenciation

                        • ce qu'est un pointeur intelligent,
                        • les différentes espèces (parce que le unique_ptr, ça ne fait pas tout)
                        • et leur bon usage,
                        sans leur avoir fait manipuler auparavant un minimum ces fichus pointeurs nus, ça m'intéresse.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          30 mai 2016 à 18:01:23

                          Tu as un magasin qui vend différents trucs. Tu sais ce qu'il vend mais tu ne sais où il est :

                          - tu appelles un taxi pour t'y mener : c'est une référence (tu sais qu'il existe, le taxi t'y a conduit).
                          - tu regardes dans un annuaire pour récupérer l'adresse : peut-être que le magasin n'existe plus (annuaire trop ancien ?), c'est un pointeur.

                          Quand tu entres dans la magasin, tu déréférences. Autant dire que si le magasin n'existe plus et que tu entres dedans, tu pourrais avoir des surprises (tu te cognes contre un mur, tu tombes dans un trou, tu entres dans un autre magasin,...) : c'est un comportement indéterminé.

                          D'autres questions ?

                          • Partager sur Facebook
                          • Partager sur Twitter
                            30 mai 2016 à 18:20:14

                            anolya a écrit:


                            D'autres questions ?


                            Il ne s'agit pas d'agiter des analogies pour le moins douteuses, mais d'enseigner C++.

                            Où est le code C++, dans ton explication ?

                            PS: et si tu emploies le mot adresse (postale), ça va entrer en conflit avec adresse en mémoire, autant dire que ton exemple va larguer ton auditoire d'entrée.

                            PS2: le problème avec C++, c'est sa construction historique par strates. Il y a (dernièrement) des strates qui sont destinées à faciliter les bons usages et simplifier la programmation. Dans certains cas, ça peut être vu d'emblée par les débutants, par exemple le "range based for loop" (foreach, quoi) dispense d'aller s'emmerder avec les itérateurs quand il y a juste des parcours séquentiels à faire ; dans d'autre cas comme les pointeurs intelligents, pour en voir l'intérêt et comprendre comment on s'en sert, il faut d'abord avoir vu le merdier qu'il y a dessous.
                            Sans compter que les unique_ptr, il faut avoir de bonne notions sur la sémantique de mouvement pour comprendre quand il fait le passer en paramètre par valeur ou par référence, et on ne peut même pas coller des shared_pointers partout parce qu'on va se retrouver avec des circularités et des fuites mémoire.

                            -
                            Edité par michelbillaud 30 mai 2016 à 18:40:59

                            • Partager sur Facebook
                            • Partager sur Twitter
                              30 mai 2016 à 19:44:51

                              michelbillaud a écrit:

                              Si tu arrives à écrire un texte qui explique, à des débutants en C++ qui ne savent pas encore ce qu'est un pointeur,une adresse, une déréférenciation

                              • ce qu'est un pointeur intelligent,
                              • les différentes espèces (parce que le unique_ptr, ça ne fait pas tout)
                              • et leur bon usage,

                              sans leur avoir fait manipuler auparavant un minimum ces fichus pointeurs nus, ça m'intéresse.

                              Facile, il suffit de leur dire que les pointeurs intelligents sont des indirections qui gèrent automatiquement la libération de la mémoire (RAII) allouée sur le Tas. Il en existe deux types : avec ownership non partagée (std::unique_ptr) et avec ownership partagée (std::shared_ptr qui possède l'ownership et std::weak_ptr qui ne prend pas l'ownership).

                              Comme ils auront lu avant les chapitres sur les indirections, la gestion des ressources, la portée et la durée de vie des variables locales, la Pile et le Tas, et sur l'ownership, ces explications seront limpides pour eux :)

                              Un jour, un étudiant a posé cette question sur les pointeurs intelligents à un de mes vieux profs en C++. Voici ce qu'il a répondu :

                              - Etudiant : Maître, expliquer les pointeurs nus, c'est une chose, mais expliquer les pointeurs intelligents, c'est totalement différent.

                              - Professeur : Non ! Pas différent, juste différent dans ton esprit. Tu dois désapprendre tout ce que tu as appris.

                              Plus sérieusement, à force d'être persuadé qu'il n'est pas possible d'expliquer les pointeurs intelligents sans passer par les pointeurs nus, n'aurais tu pas oublié l'adage "on ne peut pas montrer que c'est faux, mais seulement échouer suffisamment à montrer que ce n'est pas vrai" ? As tu suffisamment échoué ?

                              • Partager sur Facebook
                              • Partager sur Twitter
                                30 mai 2016 à 20:19:51

                                Ah, les pointeurs nus, tu appelles ça des indirections, bien joué :-)  et quels programmes leur donnes-tu à écrire pour se familiariser avec ces fameuses indirections, avant que de passer aux pointeurs intelligents ?  Tu parles de tas, très bien. Comment as tu introduit la notion d'allocation et libération sur le tas avec tes indirections ? C'est un groupe de  concepts mystérieux qu'ils doivent garder pour plus tard ?

                                Quand on enseigne, "dire que", c'est bien beau, mais ça ne passe pas. C'est toujours une bonne excuse de prof que de dire "mais ça je leur en avait pourtant parlé". Ce qui n'a pas été utilisé en pratique n'est ni compris, ni retenu.

                                (Perso je n'aurais pas trop de mal à expliquer les pointeurs intelligents à ceux qui ont un peu programmé en Java, C#, Python etc, mais des débutants avec C++ premier langage ?)

                                -
                                Edité par michelbillaud 30 mai 2016 à 20:22:56

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  30 mai 2016 à 20:52:38

                                  Non, les indirections (le terme n'est pas de moi) correspond a tout ce qui n'est pas direct... :) Les premières dont je parle, ce sont les itérateurs et les références. Les pointeurs nus, les pointeurs intelligents, etc. ne sont que des cas particulier d'indirections (et pas les plus simples, puisqu'elles font intervenir d'autres notions comme l'allocation dynamique et l'ownership).

                                  Comment tu introduis la notion d'allocation et libération sur la Pile ? Comment tu introduis la notion d'allocation et libération sur le Tas avec des pointeurs nus ? Pourquoi ca serait plus complique a expliquer avec des pointeurs intelligents ? Pourquoi tous les exercices que tu leur donnes avec des pointeurs nus ne pourraient pas être fait avec des pointeurs intelligents ?

                                  Bref, de toute façon, mon but n’était pas de te donner un exemple d'explication sur les pointeurs nus, c'est une question qu'on a déjà abordé 10 fois. Je me demandais juste si tu ne serais pas incapable d'expliquer les pointeurs intelligent sans passer par les pointeurs nus uniquement parce que tu es persuades que ce n'est pas possible.

                                  Et au final, savoir si c'est possible ou non n'est pas une question qui m’intéresse. Je VEUX pouvoir expliquer les pointeurs intelligents directement. La seule question qui m’intéresse est comment faire cela. On verra plus tard si c’était possible ou pas.

                                  -
                                  Edité par gbdivers 30 mai 2016 à 20:54:10

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    30 mai 2016 à 20:58:55

                                    C'est pour ça qu'au lieu de déclarations "je suis sûr qu'on peut", et "si tu le mets en doute c'est que t'y arrives pas" qui ne sont que des procédés rhétoriques (ou de la méthode Coué), je préfèrerais voir des textes écrits, construits, progressifs avec exercices et tout ça.

                                    L'allocation sur la pile, c'est la notion de contexte d'exécution, la pile des appels. On ne demande pas d'allocation sur la pile, elle se produit quand il y a un appel. Ca n'a guère de rapport avec l'utilisation des pointeurs.

                                    -
                                    Edité par michelbillaud 30 mai 2016 à 21:02:13

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      30 mai 2016 à 21:28:31

                                      michelbillaud a écrit:

                                      des procédés rhétoriques (ou de la méthode Coué)

                                      Ça, je te l'accorde sans probleme. :)

                                      Mais mon questionnement derrière (savoir si a force d’être persuade que le C++ s'enseigne de telle façon, on n'est pas devenu incapable de l'enseigner autrement) n'est pas du tout rhétorique.

                                      michelbillaud a écrit:

                                      je préfèrerais voir des textes écrits, construits, progressifs avec exercices et tout ça.

                                      Je veux bien que tu me donnes aussi ces textes pour les pointeurs nus, avec "leur bon usage" dont tu as parlé précédemment. (Parce que, a force de voir en entretiens d'embauche des gens incapables de gérer correctement les pointeurs nus, je crois que de tels textes, avec "leur bon usage", sont aussi rare que les cours sur les pointeurs intelligents).

                                      Et bien sur que non, je n'ai pas de tels textes. Puisque je bosse dessus. Et que cela prendra des années de recul pour savoir si les explications sont efficaces. Voire il faudra que je les réécrive plusieurs fois. Et peut être que dans plusieurs années, je conclurais que j'ai échoué a donner ces explications et qu'il n'est pas possible d'expliquer les pointeurs intelligents sans expliquer les pointeurs nus avant.

                                      Et je ne crois pas non plus que tu as écrit de tels textes (je me trompe ?) et que tu en avais conclus que ce n'est pas possible. Tu te bases sur tes aprioris. Mon approche est peut être de la méthode Coué, mais je crois que c'est la seule méthode permettant de prouver que c'est impossible de donner de tels explications. Ou pas.

                                      -
                                      Edité par gbdivers 30 mai 2016 à 21:58:59

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        30 mai 2016 à 22:03:57

                                        Quand tu les vois en entretien d'embauche, ils n'en sont plus à la présentation des notions. 

                                        On leur a montré les pointeurs nus, dans un contexte de programmation à l'ancienne, où les bonnes pratiques se résument à "faut penser à libérer un jour les trucs qu'on a alloués" (et où la présence d'exceptions fera tout s'écrouler). Ils l'ont pratiqué un peu, pour apprendre, en faisant des erreurs, et ils sont passés à autre chose.

                                        Il est certain qu'une bonne moitié n'est pas fichue de le faire correctement, parce que quelque soit le problème que tu leur pose, une bonne moitié n'est pas fichu de le faire. Quand on leur montrera les pointeurs intelligents, tu trouvera aussi que beaucoup ne sont pas fichus de les choisir correctement dans les cas de circularités. Il y a tant de choses à voir dans une formation actuelle en informatique qu'aucune n'est faite en profondeur, et maitrisée complètement par tout le monde.

                                        Mon point de vue, c'est que les pointeurs intelligents sont un bon outil (presqu'aussi bon que le garbage collector :-)) qui simplifie nettement la vie du professionnel quand on a appris à s'en servir, et que (outre que ça n'élimine pas complètement le recours aux pointeurs nus (*) on ne s'en débarrasse pas si facilement), et que d'autre part l'explication de leur fonctionnement passe par l'idée générique d'une variable qui contient l'adresse d'une donnée. Et l'expérience montre que, comme mécanisme du langage, c'est déjà assez difficile à avaler, avant même de rentrer dans les subtilités entre unique, shared, weak et raw (qui nécessitent de distinguer entre propriété, copropriété, etc dans les relations entre entités dans le modèle de données).

                                        Donc finalement, ça ajoute à la liste des choses à maitriser, même si à la fin ça simplifie. Ce n'est pas qu'on est devenu incapable d'enseigner C++ autrement, c'est que C++ a beaucoup changé, et globalement ne s'est pas simplifié.

                                        (*) par exemple https://herbsutter.com/elements-of-modern-c-style/

                                        << Always use the standard smart pointers, and non-owning raw pointers. Never use owning raw pointers and delete, except in rare cases when implementing your own low-level data structure (and even then keep that well encapsulated inside a class boundary).

                                        - If you know you’re the only owner of another object, use unique_ptr to express unique ownership.

                                        - Use shared_ptr to express shared ownership.

                                        - Use weak_ptr to break cycles and express optionality (e.g., implementing an object cache).

                                        If you know another object is going to outlive you and you want to observe it, use a (non-owning) raw pointer.
                                        >>

                                         De toutes façons, this, c'est un pointeur nu, alors faut faire avec :-)

                                        -
                                        Edité par michelbillaud 30 mai 2016 à 22:25:49

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          31 mai 2016 à 12:13:25

                                          Si je resume vos debats:

                                          *MODE Ironique ON*

                                          - Prof: "Utilise les pointeurs intelligents !!"
                                          - Eleve: "Pourquoi diable utiliser un pointeurs intelligents qui est plus long à écrire, et de surquoi un objets (donc plus lourd) qu'un simple pointeur qui correspond à mon besoin ?"
                                          - Prof: "Les pointeurs intelligents n'ont que des avantages."
                                          - Eleve: "Quels sont les inconvéniants du pointeur nu ?"
                                          - Prof: "Bah, c'est un pointeur nu".

                                          Conclusion: Eleve pas convaincu.

                                          *MODE Ironique OFF*

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            31 mai 2016 à 13:10:41

                                            Deedolith a écrit:

                                            Si je resume vos debats:

                                            *MODE Ironique ON*

                                            - Prof: "Utilise les pointeurs intelligents !!"
                                            - Eleve: "Pourquoi diable utiliser un pointeurs intelligents qui est plus long à écrire, et de surquoi un objets (donc plus lourd) qu'un simple pointeur qui correspond à mon besoin ?"
                                            - Prof: "Les pointeurs intelligents n'ont que des avantages."
                                            - Eleve: "Quels sont les inconvéniants du pointeur nu ?"
                                            - Prof: "Bah, c'est un pointeur nu".

                                            Conclusion: Eleve pas convaincu.

                                            *MODE Ironique OFF*

                                            Assez mauvais resumé. L'intéret des pointeurs intelligents n'est absolument pas le débat. Ni de savoir si on peut enseigner quelque chose sans expliquer les avantages et inconvenients. Ni meme de savoir s'il faut enseigner les pointeurs nus OU les pointeurs intelligents.

                                            (Dans un enseignement complet. Il faut parfois faire des choix en fonction de contraintes materielles, comme le temps d'enseignement disponible, mais ce n'est pas un choix basé sur la qualité du message que l'on veut transmettre).

                                            La question est l'ordre d'apprentissage.

                                            @michelbillaud

                                            Je suis d'accord qu'il y a plus de choses a connaitre pour maitriser le C++. Mais justement, si au final cela simplifie, il n'y a pas de raison que l'enseignement ne soit pas simplifié aussi. Tu parles du concept d'adresse memoire, pourquoi expliquer cela via les pointeurs nus plutot que via les references par exemple ? Pourquoi expliquer l'allocation dynamique via new plutot que via make_unique ? Tous les concepts que tu peux enseigner avec les pointeurs nus, tu peux les enseigner avec d'autres syntaxes plus safe (et plus importantes).

                                            Je crois qu'il y a maintenant des notions plus importante a apprendre avant les pointeurs nus (gestion des ressources, ownership). Et une fois ces notions apprises, la comprehension des pointeurs nus/intelligents est plus simple. Dans la liste de Sutter, les pointeurs nus sont en dernier, pourquoi commencer l'enseignement par la fin ? Sur un cours qui devra faire l'impasse sur plusieurs notions, lesquelles il faudra mettre de cote ? Je prefere que ce soit les pointeurs nus que les notions fondamentales sur la gestion des ressources.

                                            Et je crois que beaucoup d'enseignants n'ont pas compris que les pointeurs nus ne sont plus une notion fondamentale a apprendre. Et tant que cela ne sera pas assimilées, l'enseignement du C+ ne pourra pas evoluer.

                                            -
                                            Edité par gbdivers 31 mai 2016 à 13:16:32

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              31 mai 2016 à 14:18:55

                                              >les pointeurs nus ne sont plus une notion fondamentale a apprendre

                                              Vu la masse de la maintenance du vieux code C++, c'est malheureusement pas encore le cas, mais il faut y travailler, et en entreprise, cela ne va pas de soi.

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                31 mai 2016 à 14:51:16

                                                gbdivers a écrit:



                                                (Dans un enseignement complet. Il faut parfois faire des choix en fonction de contraintes materielles, comme le temps d'enseignement disponible, mais ce n'est pas un choix basé sur la qualité du message que l'on veut transmettre).


                                                Correction : il faut toujours. C'est une contrainte de base. Et ce choix oblige à faire des coupes sévères dans ce qu'on aimerait raconter. On pourrait toujours imaginer transmettre de meilleurs messages, plus complets, avec des tas de choses qui sont aussi indispensables, mais ça débordera toujours le temps dispo.

                                                Quand C++ est considéré comme un des langages possibles pour faire passer un certain nombre de connaissances et savoir-faire, et non comme un objectif en soi, il y a un moment où les exigences des uns (parler absolument de tel truc et s'abstenir complètement d'en parler un autre) font qu'on est obligé de réconsidérer le choix du langage si on veut atteindre les objectifs.

                                                Mais la problématique est différente si tu animes une formation "maitrisez C++ en 1 mois à plein temps".

                                                -
                                                Edité par michelbillaud 31 mai 2016 à 14:51:33

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  31 mai 2016 à 14:56:22

                                                  bacelar a écrit:

                                                  Vu la masse de la maintenance du vieux code C++, c'est malheureusement pas encore le cas, mais il faut y travailler, et en entreprise, cela ne va pas de soi.

                                                  Tu preferes embaucher quelqu'un qui ne connait pas la syntaxe des pointeurs nus, mais qui connait les concepts d'indirection (adresse memoire), d'ownership, de gestion des ressources, ou quelqu'un qui connait la syntaxe des pointeurs nus, mais pas toutes ces notions ?

                                                  J'utilise Qt au boulot, donc des pointeurs nus partout. Pourtant, je prefere sans probleme le premier gars. D'ailleurs, les questions que l'on pose en entretien vise a savoir s'il a ces notions. On se pose meme pas la question de savoir s'il connait la syntaxe des pointeurs nus. S'il ne connait pas la syntaxe (mais qu'il connait ces notions), cela prendra 5 min pour lui expliquer les pointeurs nus. Par contre, s'il ne connait pas ces notions, il fera du code de merde s'il utilise les pointeurs nus. Le choix est vite fait.

                                                  Le fait de connaitre les pointeurs nus est qu'un detail syntaxique. (Tout comme ne pas connaitre nullptr, default/delete, et pleins d'autres syntaxes du C++11/14. Ce sont jamais que des details syntaxiques. C'est mieux de connaitre. Mais si un candidat ne connait pas, mais connait les notions importantes, ca pose pas de probleme)

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    31 mai 2016 à 15:01:41

                                                    michelbillaud a écrit:

                                                    Correction : il faut toujours. C'est une contrainte de base. Et ce choix oblige à faire des coupes sévères dans ce qu'on aimerait raconter. On pourrait toujours imaginer transmettre de meilleurs messages, plus complets, avec des tas de choses qui sont aussi indispensables, mais ça débordera toujours le temps dispo.

                                                    C'est bien comme cela que je vois les choses. Et donc, si on donne un message incomplet, il est preferable de donner les notions importantes, plutot que les details syntaxiques.

                                                    On est juste pas d'accord sur ce qui est important et ce qui est accessoire.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      31 mai 2016 à 15:18:38

                                                      Salut,

                                                      Si vous permettez, gbdivers et michebillaud, je vais m'interposer entre vous deux en disant qu'il est finalement très facile d'introduire la notion de pointeur (sans faire intervenir la gestion dynamique de la mémoire), puis de partir -- quoi qu'il arrive -- sur les pointeurs intelligents, afin d'en démontrer l'usage.

                                                      Car il n'y a que deux question à se poser concernant les pointeurs : C'est quoi? et A quoi ca sert ?

                                                      La réponse à la première question est : un pointeur, c'est une valeur numérique entière (généralement non signée) représentant l'adresse mémoire (RAM ou autre) à laquelle se trouve une information d'un type donné.

                                                      Une fois que l'on a compris cela, on a -- pour ainsi dire -- compris le reste, car il "n'y a plus qu'à" indiquer la manière d'accéder à la donnée qui se trouve à l'adresse mémoire représentée par le pointeur (déréférencement, indirection, ...).

                                                      La réponse à la deuxième question se fait en plusieurs parties, car il y a plusieurs cas d'utilisation des pointeurs :

                                                      Le premier (qui sera rendu obsolète une fois que std::optional sera sorti de l'espace de noms experimental), c'est d'avoir la possibilité de "faire référence" (au travers de son adresse) à une donnée qui peut ne pas exister, et cela n'a rien à voir avec l'ownership ou la gestion dynamique de la mémoire.  Cela nous permet "tout simplement" de dire que l'on peut décider de fournir une adresse "connue pour être invalide" (nullptr) afin qu'on ne veut pas transmettre l'information optionnelle

                                                      (nota : ce cas d'utilisation pourrait parfaitement être expliqué en dernier ;) )

                                                      Le deuxième cas d'utilisation des pointeurs a trait -- de manière générale -- à la gestion dynamique de la mémoire, et donc à tout ce qui a trait à l'ownership.  Et c'est ce cas de figure là qui pose tous les problèmes, car :

                                                      • une allocation dynamique peut échouer en lançant une exception
                                                      • si on perd l'adresse d'un élément alloué dynamiquement avant de l'avoir explicitement libérée, on constate une fuite mémoire
                                                      • si on essaye d'accéder  à un élément alloué dynamiquement mais dont la mémoire a déjà libéré, on constate un comportement indéfini
                                                      • si on essaye de libérer la mémoire allouée à un élément dont la mémoire a déjà été libérée, on constate à une tentative de double libération de la mémoire, se traduisant par un comportement indéfini

                                                      Or, il se fait que les pointeurs intelligents sont -- justement -- expressément développés pour éviter tous les problèmes que je viens de citer, ainsi que leurs conséquences (car ce n'est pas le fait qu'une allocation dynamique de la mémoire puisse échouer qui pose problème, mais les conséquence de la levée d'une exception).

                                                      Et de plus, la STL nous fournit suffisamment de types de "conteneurs" différents pour que nous n'ayons même pas besoin de nous inquiéter de l'allocation dynamique de la mémoire avant d'avoir abordé les notions d'héritage et de polymorphisme.

                                                      Dés lors, à partir du moment où l'on explique que toutes les données vont forcément se trouver en mémoire et que l'ordinateur va très souvent utiliser l'adresse mémoire à laquelle se trouve une donnée particulière, on dispose d'assez d'information pour introduire la notion de pointeur, et donc la notion de this, qui n'est que "l'adresse mémoire à laquelle se trouve l'élément en cours d'utilisation" (ce qui était la question d'origine, faut il le rappeler ;) )

                                                      Et le simple d'avoir cette information (qui ne sera -- au demeurant -- nécessaire qu'à partir du moment où il sera question de fonctions membres!)  pour se permettre d'attendre d'avoir réellement besoin de recourir à l'allocation dynamique de la mémoire (en ayant recours aux pointeurs intelligents).

                                                      ET donc, au final :

                                                      michelbillaud, je suis d'accord avec toi sur un point : il semble difficile d'aborder la notion de pointeurs intelligents sans avoir abordé la notion de pointeurs, MAIS il suffit d'avoir expliqué ce qu'est un pointeur pour être en mesure d'aborder la notion de pointeurs intelligents

                                                      Pour le reste, je suis totalement d'accord avec gbdivers : la première fois qu'un étudiant entend parler de gestion dynamique de la mémoire, cela devrait se faire... au travers de pointeurs intelligents.

                                                      Et je te vois déjà venir, Michel : tu vas sans doute me dire quelque chose comme "oui, mais c'est quand même intéressant de permettre à l'étudiant de voir un peu "ce qu'il y a sous le capot des différentes collections, et comment elle fonctionnent.".

                                                      Personne -- en tout cas, ni moi, ni (à ma connaissance) gbdivers -- ne dit le contraire. La seule chose, c'est que nous (en tout cas moi, et à ma connaissance gbdivers) plaidons pour que cette "visite des entrailles des différentes collections" soit reportée à un moment où l'étudiant a déjà eu l'occasion de prendre un peu de bouteille, car cela permettra d'avoir une courbe d'apprentissage beaucoup plus souple. 

                                                      Et donc, nous plaidons pour qu'elle se fasse après avoir appris à utiliser les pointeurs intelligents (et donc largement après avoir abordé les problèmes propres à l'OO que sont l'héritage et le polymorphisme).

                                                      Deedolith a écrit:

                                                      Si je resume vos debats:

                                                      *MODE Ironique ON*

                                                      - Prof: "Utilise les pointeurs intelligents !!"
                                                      - Eleve: "Pourquoi diable utiliser un pointeurs intelligents qui est plus long à écrire, et de surquoi un objets (donc plus lourd) qu'un simple pointeur qui correspond à mon besoin ?"
                                                      - Prof: "Les pointeurs intelligents n'ont que des avantages."
                                                      - Eleve: "Quels sont les inconvéniants du pointeur nu ?"
                                                      - Prof: "Bah, c'est un pointeur nu".

                                                      Conclusion: Eleve pas convaincu.

                                                      *MODE Ironique OFF*

                                                      C'est bien pour cela qu'il est plus que temps de bousculer les profs pour qu'ils prennent conscience des avantages des pointeurs intelligents, et pour qu'ils soient en mesure de les expliquer ;)

                                                      bacelar a écrit:

                                                      Vu la masse de la maintenance du vieux code C++, c'est malheureusement pas encore le cas, mais il faut y travailler, et en entreprise, cela ne va pas de soi.

                                                      C'est bien pour cela qu'on ne prétend absolument pas qu'il faut ne voir que les pointeurs intelligents. On "simplement" dit qu'il faut les voir avant le gestion manuelle des ressources allouée dynamiquement :D.

                                                      Ceci dit, l'objectif idéal (quoi que chimérique, je te l'accorde) serait malgré tout d'arriver à moderniser toute la base de code de manière à ce que tous les pointeurs associés à l'ownership soient des pointeurs intelligents :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
                                                        31 mai 2016 à 16:11:15

                                                        koala01 a écrit:

                                                        je vais m'interposer entre vous deux

                                                        Tu prends des risques :)

                                                        koala01 a écrit:

                                                        il est finalement très facile d'introduire la notion de pointeur (sans faire intervenir la gestion dynamique de la mémoire), puis de partir -- quoi qu'il arrive -- sur les pointeurs intelligents, afin d'en démontrer l'usage.

                                                        Cf ma question precedente : "pourquoi expliquer cela [le concept d'adresse memoire] via les pointeurs nus plutot que via les references par exemple ?"

                                                        Je commence par expliquer le concept d'indirection (adresse memoire) via les references et iterators (on ne peux pas expliquer un concept abstrait sans utiliser des exemples concrets), puis les pointeurs intelligents. Les pointeurs nus sont abordés dans un chapitre complementaire et ne sont absolument pas necessaire pour le reste du cours.

                                                        Definitivement, je ne vois rien qui ne peut pas etre expliqué sans les pointeurs nus (a part les problemes que l'on a quand on utilise des pointeurs nus...)

                                                        -
                                                        Edité par gbdivers 31 mai 2016 à 16:11:43

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          31 mai 2016 à 16:53:14

                                                          gbdivers a écrit:

                                                          Tu prends des risques :)

                                                          Au choix :

                                                          "Une vie sans risque est une soupe sans sel" ou

                                                          L'argent et la peur, c'est deux choses que je n'ai jamais connues :D

                                                          Cf ma question precedente : "pourquoi expliquer cela [le concept d'adresse memoire] via les pointeurs nus plutot que via les references par exemple ?"

                                                          Je commence par expliquer le concept d'indirection (adresse memoire) via les references et iterators (on ne peux pas expliquer un concept abstrait sans utiliser des exemples concrets), puis les pointeurs intelligents. Les pointeurs nus sont abordés dans un chapitre complementaire et ne sont absolument pas necessaire pour le reste du cours.

                                                          Je suis tout à fait d'accord avec toi, sur le fond, du moins...

                                                          Car la notion d'indirection n'est en réalité l'abstraction d'un fait technique dont je trouve important que l'étudiant prenne conscience rapidement : l'ordinateur n'ira jamais chercher ses données "dans l'air du temps", si bien que, tôt ou tard, les données se retrouveront "quelque part en mémoire", et qu'il est possible d'y accéder par "l'adresse mémoire" tout comme il est possible de se rendre chez quelqu'un grace à son adresse postale (désolé michel pour la comparaison, vu que tu ne semble pas les apprécier...)

                                                          De plus, il y a toujours le fameux problème de this,  qui ne peut valablement être expliqué qu'au travers de la notion de pointeur nu, ou, du moins, qu'au travers de la définition d'un pointeur que j'ai donnée dans mon intervention précédente.

                                                          Or, cette notion (et la signification de *this dans bien des cas) doit être expliquée **relativement** rapidement (entre autres, dés que l'on aborde la notion d'opérateur, et leurs fameux return *this;  ce qui risque d'arriver avant les notions nécessitant le recours à la gestion dynamique de la mémoire).

                                                          C'est pour cela que je dis que oui, il y a tout à fait moyen d'aborder la notion d'indirection au travers de notions telles que les références ou les itérateurs, et, oui, tout ce qui a trait à la gestion dynamique de la mémoire doit être abordé au travers des pointeurs intelligents.

                                                          Par contre, la définition même de ce qu'est un pointeur doit sans doute apparaitre quelque part entre les deux (ou, en tout état de cause, avant de commencer à parler des pointeurs intelligents)

                                                          -
                                                          Edité par koala01 31 mai 2016 à 16:54:24

                                                          • 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
                                                            31 mai 2016 à 19:59:09

                                                            koala01 a écrit:

                                                            De plus, il y a toujours le fameux problème de this,  qui ne peut valablement être expliqué qu'au travers de la notion de pointeur nu, ou, du moins, qu'au travers de la définition d'un pointeur que j'ai donnée dans mon intervention précédente.

                                                            Or, cette notion (et la signification de *this dans bien des cas) doit être expliquée **relativement** rapidement (entre autres, dés que l'on aborde la notion d'opérateur, et leurs fameux return *this;  ce qui risque d'arriver avant les notions nécessitant le recours à la gestion dynamique de la mémoire).

                                                            C'est une bonne idee, revenons au probleme du this. (A force de raconter mes betises, j'avais oublie la question du PO).

                                                            this = pointeur nu = interdit de l'utiliser ! :D

                                                            Plus serieusement, si on utilise this dans un membre, sans le "sortir" de la fonction, on n'a pas reellement besoin de savoir que c'est un pointeur nu, un pointeur intelligent, ou n'importe quel type de pointeur. Savoir que c'est un pointeur et qu'on peut l'utiliser avec -> est suffisant.

                                                            Le probleme de this est lorsque l'on va essayer de l'utiliser en dehors de la fonction membre. C'est le cas classique avec les connexions de Qt avec une fonction lambda. Mais egalement avec la question du PO. Il y a une tres grosse difficultes a passer this a une fonction ou un constructeur, qui vont etendre la duree de vie du pointeur potentiellement au dela de la duree de vie de l'objet.

                                                            Avec Qt, on peut contourner le probleme en creant un QPointeur sur this (qui va detecter la destruction de l'objet). Mais dans le cas general, pointeur nu ou intelligent ne regle pas le probleme. Il faut comprendre les problemes d'ownership, de duree de vie, et plus generalement d'indirection. Comprendre ces notions est a mon sens plus fondamentale que de comprendre une syntaxe particuliere (nu ou intelligent).

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              31 mai 2016 à 22:25:30

                                                              Hé bien, prenons, justement, le cas d'une fonction libre (ou d'une fonction membre publique d'une autre classe) autre que l'un des cinq grands (dont une ne peut de toutes manières pas prendre de paramètre) appelée depuis l'objet courant.

                                                              Autrement dit, si notre objet courant est de type MyClass, nous aurions quelque chose ressemblant à

                                                              void foo(MyClass /* const */ & );
                                                              /*OU OU OU */
                                                              void bar(Myclass * );
                                                              /* OU ENCORE */
                                                              class Truc{
                                                              public:
                                                                  void foo(MyClass /* const */ &);
                                                                  /* OU OU OU */
                                                                  void bar(MyClass * );
                                                              };

                                                              Il n'est jamais question d'ownership dans ces fonctions (étant entendu que bar n'appellera jamais delete sur le pointeur recu), mais bar permet (en attendant de disposer de std::optional, de représenter un paramètre optionnel.

                                                              Si nous voulons pouvoir appeler ces fonctions depuis notre classe, c'est qu'elle prend une forme proche de

                                                              class MyClass{
                                                              public:
                                                                  void truc(){
                                                                     // appel de la fonction libre foo
                                                                     foo(*this);
                                                                     // appel de la fonction libre bar
                                                                     bar(this);
                                                                  }
                                                                  void machin(Truc & t){
                                                                      // appel de la fonction foo membre de Truc
                                                                      t.foo(*this);
                                                                      // appel de la fonction bar membre de Truc
                                                                      t.bar(this);
                                                                  }
                                                              };

                                                              C'est le cas typique, et le plus simple que l'on puisse trouver, dans lequel nous aurons besoin de recourir à this (ou à ce qui est pointé par this) : on veut transmettre "l'objet courant" à une autre fonction.

                                                              A l'extrême limite, je suis d'accord avec toi : il n'y a même pas besoin d'introduire la notion de pointeur ici : on peut tout à fait dire que "this représente l'adresse mémoire à laquelle se trouve l'objet courant, et, si tu veux pouvoir accéder à l'objet en question, il faut utiliser *this: foo(*this) permet d'envoyer l'objet courant à la fonction foo".

                                                              Mais cela pose un problème pour bar, car là, la notion de pointeur devient nécessaire. 

                                                              Par contre, les notions d'ownership et de durée de vie n'ont absolument aucune raison d'être abordée : si l'étudiant n'a pas appris qu'il faut veiller à libérer la mémoire des pointeurs lorsqu'on n'en a plus besoin, il n'a absolument aucune raison d'essayer de le faire.

                                                              Et puis, cela plaide en faveur de mon point de vue : un pointeur nu passé en paramètre devrait systématiquement être considéré comme un pointeur que l'on peut utiliser, mais pour lequel nous n'avons absolument pas à nous inquiéter des problème de durée de vie.  Du moins, tant que l'on n'est pas dans un contexte multi-threadé, cette manière de voir les choses n'a absolument aucune raison de poser le moindre problème.

                                                              Et, étant donné que les raisons "de base" d'avoir besoin de this sont beaucoup plus simples que les raisons d'avoir recours à la gestion dynamique de la mémoire, il me semble malgré tout "logique" d'aborder cela avant d'aborder "toute la mécanique" de la gestion des ressources dynamiques.

                                                              Mais, ceci dit, je reste tout à fait d'accord avec toi sur le reste : dés qu'il est question d'ownership et / ou de durée de vie de la ressource pointée, les pointeurs nus doivent être purement et simplement bannis ;)

                                                              Et j'irais même plus loin: quand std::optional sera disponible, il ne devrait plus y avoir la moindre raison pour fournir un pointeur nu comme argument à une fonction; nous pourrons donc parler de this comme d'une "curiosité historique" du langage, et nous contenter de dire "this représente l'adresse mémoire à laquelle se trouve l'objet courant... si vous en avez besoin utilisez  *this"...

                                                              Et qui sait??? même si j'ai un sérieux doute à ce sujet (cela casserait très certainement beaucoup trop de code), this pourrait finir par être ce qu'il aurait du être depuis le début : une référence sur l'objet courant, et la notion de pointeur pourrait alors ne plus exister qu'au travers des pointeurs intelligents :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

                                                              Petite question concernant l'utilisation de this

                                                              × 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