IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Le pointeur 'This'


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 24
    Points : 13
    Points
    13
    Par défaut Le pointeur 'This'
    Bonjour,

    J'essaie de faire un code d'une liste chainée qui contient 20 objets, dans mon exemple, j'empile 20 lancés de vitesse différentes que j'ai inventé.
    Par la suite, j'aimerais utiliser le pointeur 'This' pour me cibler les lancer qui atteint la vitesse ''91''.
    Par contre, je comprends pas trop le principe de 'This' et comment bien le programmer.
    Voici ce que j'ai fait, et je ne crois pas avoir bien codé 'This' car il n'a aucun impact lorsque je fais 'run'
    Est-ce que quelqu'un pourrait m'éclairer
    Merci!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
     
    class Lancee {
        int taille, *contenu, nb;
    public:
        Lancee(int taille_max);
        ~Lancee();
        virtual void ajouter_au_sommet(int k);
        virtual int prendre_au_sommet();
    };
    // Cette mÈthode ci-dessous qui est le constructeur permet
    // díinitialiser la pile.
    Lancee::Lancee (int taille_max) {
        taille = taille_max;
        contenu = new int[taille];
        nb = 0;
    }
    Lancee::~Lancee()
    {
        delete[] contenu;
    }
    void Lancee::ajouter_au_sommet(int k)
    {
        if(nb < taille) { contenu[nb] = k; nb++; }
        else abort();
    }
    int Lancee::prendre_au_sommet()
    {
        if(nb > 0) { nb--; return contenu[nb]; }
        else abort();
    }
    int main(int argc, char **argv)
    {
        Lancee Lancee(20);
        Lancee.ajouter_au_sommet(90);
        Lancee.ajouter_au_sommet(88);
        Lancee.ajouter_au_sommet(102);
        Lancee.ajouter_au_sommet(91);
        Lancee.ajouter_au_sommet(92);
        Lancee.ajouter_au_sommet(91);
        Lancee.ajouter_au_sommet(83);
        Lancee.ajouter_au_sommet(100);
        Lancee.ajouter_au_sommet(93);
        Lancee.ajouter_au_sommet(97);
        Lancee.ajouter_au_sommet(88);
        Lancee.ajouter_au_sommet(84);
        Lancee.ajouter_au_sommet(101);
        Lancee.ajouter_au_sommet(99);
        Lancee.ajouter_au_sommet(95);
        Lancee.ajouter_au_sommet(96);
        Lancee.ajouter_au_sommet(83);
        Lancee.ajouter_au_sommet(105);
        Lancee.ajouter_au_sommet(91);
        Lancee.ajouter_au_sommet(98);
        cout << Lancee.prendre_au_sommet() << endl;
     
        cout << Lancee.prendre_au_sommet() << endl;
        cout << Lancee.prendre_au_sommet() << endl;
        cout << Lancee.prendre_au_sommet() << endl;
    }
    class Afficheur
    {
    public:
        Afficheur (int = 0); // Constructeur par dÈfaut
        void afficherLancee () const;
    private:
        int Lancee;
    };
    Afficheur::Afficheur(int a) { Lancee = a; } // Constructeur
    void Afficheur::afficherLancee () const
    {
        cout << " Lancee = " << Lancee << endl
        << " this-> Lancee = " << this-> Lancee << endl
        << " (*this). Lancee = " << (*this). Lancee << endl;
    }
    int Afficheur ()
    {
        class Afficheur Lancee (91);
        Lancee.afficherLancee();
     
        return 0;
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    Code plutôt "propre" pour un débutant (indentation respectée, nom de variable non cryptique, etc...).

    MAIS on sent bien que le cours que vous suivez est de bien piètre qualité car il y a beaucoup beaucoup d'erreurs de conception.(using namespace std, pointeurs nus, VLA, mauvais nommage de classe, allocation dynamique, convention de nommage non cohérente, pas de std::vector ou de std::list, etc...)
    C'est des erreurs récurrentes provenant de mauvais cours de C++, tout droit pompés de vieux cours de C, même plus à jour même pour du C.

    Plutôt que de vous reprendre sur chacun des point, le plus simple, et le plus efficace, c'est de reprendre avec un bon cours de C++.

    Pour être plus précis sur le "This".
    Bin, déjà, le C++, c'est casse sensitive, donc "This", c'est pas la même chose que "this".
    Je vois 2 grands type d'usage de "this" :
    - donner un pointeur sur l'objet courant comme argument d'une fonction.
    - modifier l'ordre d'évaluation d'un identifiant (unqualified name lookup https://en.cppreference.com/w/cpp/la...alified_lookup)

    Votre code ne l'utilise pas lors d'un appel de fonction, on est donc dans le 2ème cas.
    L'usage de this, dans ce cas, permet d'utiliser des champs de l'objet courant, même s'il existe des paramètres de la fonction courante ou des variables locales de même nom.
    Dans votre cas, vous n'êtes pas dans ce cas de "collision" de nom. Votre "this" est donc inutile, voire contre-productif car un programmeur expérimenté cherchera où sont le paramètre ou la variable local qui justifie l'usage de ce "this".
    Généralement, on essaye de choisir des noms de paramètres et de variables locales qui ne collisionnent pas avec les champs d'une instance de classe. L'usage de ce type de "this" est donc très anecdotique.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    A vrai dire, tu n'as -- le plus souvent -- absolument pas besoin d'utiliser le pointeur this! Mais, ce que tu veux sans doute, c'est comprendre ce qu'est effectivement ce pointeur

    Donc, le pointeur this est un pointeur -- une donnée numérique entière (généralement) non signée qui contient l'adresse mémoire à laquelle se trouve l'objet du type indiqué -- correspondant à l'élément en cours d'utilisation, dont la transmission comme paramètre est systématiquement ajoutée (de manière implicite : le compilateur se charge de le faire pour toi) à chaque fois que tu fais appel à une fonction membre d'une de tes classes.

    Le but de ce pointeur est de nous permettre de lever les ambiguïtés entre les données qui font partie de ta classe (car une classe, c'est surtout un agrégat de données, au même titre qu'une structure) et les éventuels paramètres que tu devras transmettre à une fonction.

    S'il n'y a aucune ambiguïté l'utilisation de this à l'intérieur d'une fonction membre est strictement implicite, ce qui fait qu'il n'y a absolument aucune différence, si nous créons une classe proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MyClass{
    public:
        void foo();
        void bar(int i);
    private:
        int i;
    }
    entre un code qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::foo(){
        this->i *=2;
    }
    et un code qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::foo(){
        i *=2;
    }
    (car il semble évident que le seul i qui existe au niveau de foo est ... la donnée membre de la classe)

    Par contre, au niveau de bar(), les choses seraient un peu plus compliquées, parce que,a priori, si nous venions à écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::bar(int i){
        i *=2;
    }
    le i dont nous modifierions la valeur correspondrait au i qui a été transmis comme paramètre, car le paramètre va "cacher" -- au sein de la classe -- la donnée membre de la classe.

    Si bien que, si l'on veut pouvoir effectivement modifier la valeur de la donnée de la classe (par opposition à la valeur du paramètre), nous devrions avoir recours à un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::bar(int i){
        this->i *=2;
    }
    et que, comme nous pouvons -- de ce fait -- lever l'ambiguité, nous pourrions même nous permettre l'écriture d'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::bar(int i){
        this->i *=i;
    }
    qui aura pour résultat de remplacer la valeur de la donnée de la classe par le produit de la valeur de la classe par la valeur du paramètre.

    Mais il est un peu moche d'avoir recours à this pour lever ce genre d'ambiguité (qui, soit dit en passant serait mise en évidence par un compilateur bien réglé), car il est finalement très simple de l'éviter : il "suffit" de choisir un nom différent pour l'une des données (que ce soit la donnée membre ou le paramètre n'a pas beaucoup d'importance).
    Par exemple, nous pourrions décider de renommer la donnée membre sous la forme de m_i, ce qui donnerait un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MyClass{
    public:
        void foo();
        void bar(int i);
    private:
        int m_i;
    }
    et qui nous autoriserait donc à écrire notre fonction bar sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::bar(int i){
        m_i *= i;
    }
    vu que les deux noms sont clairement différents

    Ou nous pourrions aussi envisager de renommer le paramètre sous une forme qui serait alors proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MyClass{
    public:
        void foo();
        void bar(int param);
    private:
        int i;
    }
    ce qui aurait un résultat similaire : i et param étant de fait deux noms totalement différents
    (et, bien sur, nous pouvons aussi décider de renommer les deux : d'utiliser m_i pour la donnée membre et param pour le paramètre de la fonction )

    Par contre, il y a quelque situations trèès particulières dans lesquelles l'utilisation de this sera -- effectivement -- absolument obligatoire. Mais comme ces situations surviennent lorsque l'on commence à jouer avec les arcanes du langage, et il sera toujours temps de t'en parler plus tard

    Ceci étant dit, si tu tiens toujours à utiliser this, voici à peu près à quoi pourrait ressembler ton code, en le modifiant de telle manière à ce qu'il soit utilisé à chaque fois que possible (en gros : à chaque fois que tu voudra manipuler l'une des données membres de ta classe):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Lancee {
        int taille, *contenu, nb;
    public:
        Lancee(int taille_max);
        ~Lancee();
        virtual void ajouter_au_sommet(int k);
        virtual int prendre_au_sommet();
    };
    // Cette mÈthode ci-dessous qui est le constructeur permet
    // díinitialiser la pile.
    Lancee::Lancee (int taille_max) {
        this->taille = taille_max;
        this->contenu = new int[taille];
        this->nb = 0;
    }
    Lancee::~Lancee()
    {
        delete[] this->contenu;
    }
    void Lancee::ajouter_au_sommet(int k)
    {
        if(this->nb < this->taille) { this->contenu[this->nb] = k; nb++; }
        else abort();
    }
    int Lancee::prendre_au_sommet()
    {
        if(this->nb > 0) { nb--; return this->contenu[this->nb]; }
        else abort();
    }
    NOTA: il y aurait énormément de remarques à faire au sujet de ces quelques lignes de code, mais comme mon intervention a déjà l'allure d'un roman, je vais les garder pour plus tard
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 24
    Points : 13
    Points
    13
    Par défaut
    Merci à toi Koala01, ça m'a mis sur la piste et fait comprendre le pointeur this.

    Et effectivement dans le cadre de l'exercice, je n'ai pas le choix de continuer avec this.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Pointeur this et événement OnClick
    Par Argonz dans le forum Général JavaScript
    Réponses: 10
    Dernier message: 02/11/2009, 11h32
  2. Réponses: 4
    Dernier message: 02/08/2007, 14h11
  3. Question sur le pointeur this
    Par Core8 dans le forum C++
    Réponses: 4
    Dernier message: 29/03/2007, 14h31
  4. pointeur this - c++ builder
    Par mathieu57 dans le forum C++Builder
    Réponses: 7
    Dernier message: 03/03/2006, 14h19
  5. [MFC] Pointeur this et fonctions statiques
    Par Yellowmat dans le forum MFC
    Réponses: 5
    Dernier message: 08/02/2005, 10h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo