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

Langage C++ Discussion :

this->champ vs Class::champ


Sujet :

Langage C++

  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut this->champ vs Class::champ
    Bonjour,

    J'ai une classe RangeWidget qui possède un champ float max_m. J'ai demandé à CLion de générer un setter pour ce champ. Voici le code généré :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void RangeWidget::setMax_m(float max_m)
    {
        RangeWidget::max_m = max_m;
    }
    Je me serais attendu à cette écriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void RangeWidget::setMax_m(float max_m)
    {
        this->max_m = max_m;
    }
    J'allais dire "je ne connaissais pas cette écriture Class::champ" mais en y réfléchissant bien, je l'avais déjà vu pour éviter des conflits lors d'héritage multiple.

    Ma question est très simple : faut-il préférer this->champ ou Class::champ ?

    Merci !

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Il y même 4 possibilités pour un membre non statique dans une fonction membre non statique s'il n'y a pas d'ambiguité.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    this->RangeWidget::max_m;
    RangeWidget::max_m;
    this->max_m;
    max_m;
    Laquelle est préférable : la dernière, c'est clair et net. En ayant évité d'avoir un paramètre de même nom.
    Sinon j'ai une préférence pour this->max_m s'il n'y a pas d'ambiguïté et sur la première sinon.

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En théorie, Class::champ est un nom qualifié, recherché différement des noms non qualifiés.
    Le compilateur doit chercher le scope Class puis parmi les variables de ce scope. Et si le scope est une classe, vérifier que *this en dérive.

    this->champ au contraire, est un accès par un nom non qualifié, mais dans *this uniquement.

    D'un point de vue strictement lié à la norme, this-> est plus efficace, car saute l'étape de recherche dans les variables locales.
    S'il y a une différence, c'est uniquement sur le temps de compilation.

    En pratique, il est hautement probable que la différence soit nulle, le compilateur pouvant avoir en interne une table de noms connus, comprenant notamment les noms trouvés dans *this.

    Par contre, pour la lecture du code, le plus clair est encore la troisième solution: utiliser un préfixe ou un suffixe pour les membres (m_champ ou champ_).
    L'effet est alors équivalent à Class::champ.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    l'écriture RangeWidget::max_m; n'est pas pour appeler un attribut statique ?


    Et sinon :: (les 2 2 points) c'est l'opérateur de résolution de portée

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Normalement, c'est plus pour ca, mais je crois bien que cela fonctionne.
    Même si, en me creusant la tête, je ne me souviens de m'en être servi que pour des fonctions.

    d'après cppreference.com, le "qualified_lookup" peut chercher un "class member (including static and non-static functions, types, templates, etc)".
    Donc, oui, ca doit fonctionner
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Ouais cela doit fonctionner, parce que de souvenirs , c'est l'écriture que l'on utilise pour résoudre les problèmes d'héritage multiple en losange, ... en spécifiant quelle classe mère on choisit

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    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 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Je pense que les concepteurs/implémenteurs de CLion ont pris la 2ème écriture car cela donne une implémentation la plus "robuste".
    La plus simple, la 4ème, est sujet aux collisions de noms entre l'argument et le champ.
    La plus "naturelle", la 3ème, oblige l'IDE à déterminer si le champ est statique ou pas, et le code pètera si l'utilisateur change la nature static/d'instance du champs.
    La 1ère est plus complexe (mais en code auto-généré, on sent fout) et dispose des mêmes limitations que la 3ème.

  8. #8
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Citation Envoyé par bacelar Voir le message
    La plus "naturelle", la 3ème, oblige l'IDE à déterminer si le champ est statique ou pas, et le code pètera si l'utilisateur change la nature static/d'instance du champs.
    La 1ère est plus complexe (mais en code auto-généré, on sent fout) et dispose des mêmes limitations que la 3ème.
    Non. L'écriture this->membreStatique est valide, tout comme ptrVersObj->membreStatique et obj.membreStatique. Et cela vaut à la fois pour les variables membres statiques et les fonctions membres statiques.

    Exemple :
    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
    #include <iostream>
     
    struct Foo {
    	static int bar;
    	static void baz() { bar = 3; }
    	Foo() {
    		this->baz();
    		this->Foo::baz();
    		this->bar = 0;
    		this->Foo::bar = 2;
    	}
    };
     
    int Foo::bar = 1;
     
    int main()
    {
    	std::cout << Foo::bar; // prints "1"
    	Foo foo;
    	std::cout << foo.bar; // prints "2"
    	foo.baz();
    	std::cout << (&foo)->bar; // prints "3"
    	(&foo)->baz();
    	return 0;
    }
    A part ça, par rapport au sujet du fil, personnellement, je préfère préfixer toutes les variables membres privées par m_ pour les distinguer des paramètres de fonction.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    je préfère préfixer toutes les variables membres privées par m_ pour les distinguer des paramètres de fonction.
    je ne préfère pas préfixer toutes les variables membres privées, mais préfixer tous les paramètres de fonction par new_, param_, input_, ...

  10. #10
    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,
    Citation Envoyé par foetus Voir le message
    je ne préfère pas préfixer toutes les variables membres privées, mais préfixer tous les paramètres de fonction par new_, param_, input_, ...
    Humm...
    1. new ne semble intéressant que lorsque le paramètre est destiné à redéfinir une valeur.
    2. param_ n'apporte strictement rien à la lecture de la signature car on se doute bien que c'est un paramètre
    3. input_ pareil : tout paramètre étant forcément une donnée en entrée (et éventuellement une donnée en sortie, bien que ce soit déconseillé)


    A choisir, je préfère préfixer ou suffixer les données membres, de manière à garder les identifiants non préfixés pour les paramètres, de manière à ce que leur identifiant indique leur raison d'être
    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

  11. #11
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Citation Envoyé par koala01 Voir le message
    param_ n'apporte strictement rien à la lecture de la signature car on se doute bien que c'est un paramètre
    Par contre, dans certains milieux, cela peut avoir un intérêt dans la lecture de l'implémentation d'une fonction.

    Tant que l'implémentation reste courte, param_ ne sert à rien à part alourdir la lecture. Mais, une fois que des développeurs auront bien massacré le code en transformant la petite fonction de départ en fonction de 200 km, alors les préfixes param_ aideront un petit peu les pauvres lecteurs du code.

    Dans le code que je maintiens, dans certaines fonctions, tous les paramètres sont préfixés par p, par exemple pTrucMachin.

    D'ailleurs, par le passé, Oncle Bob préfixait :
    • les paramètres par the
    • les variables locales par a ou an,
    • les variables membres non statiques par its (ou is pour les booléens) et
    • les variables membres statiques par their.

    Source : http://wiki.c2.com/?UncleBobsNamingConventions

    Cela dit, personnellement, je n'écris pas de préfixe pour les paramètres de fonction.

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Merci pour vos commentaires ! Je passe en résolu.

    PS : Il va sans dire que j'ai modifié le code généré en ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void RangeWidget::setMax(float max)
    {
        max_m = max;
    }

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

Discussions similaires

  1. Class champ Image
    Par retwas dans le forum C#
    Réponses: 0
    Dernier message: 03/04/2011, 12h32
  2. Réponses: 2
    Dernier message: 29/11/2010, 12h17
  3. Réponses: 2
    Dernier message: 21/08/2008, 12h46
  4. Listé déroulante classée + champ « tous »
    Par joshua12 dans le forum IHM
    Réponses: 2
    Dernier message: 20/06/2007, 14h28
  5. Plusieurs champs, même classe, nombre inconnu
    Par anayathefirst dans le forum Struts 1
    Réponses: 2
    Dernier message: 25/01/2007, 14h19

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