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

Contribuez C++ Discussion :

Le langage D


Sujet :

Contribuez C++

  1. #141
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    Et cela n'a pas d'importance dans bien des cas.

    Je me tape complètement de savoir si une fonction est virtuelle ou non quand je lis le code. Par contre, savoir si je peux la surcharger ou non est important. Et si je la surcharge, le compilo saura qu'elle doit être virtuelle. Mais toi, ce qui t'importe, c'est que tu puisses la surcharger.

    Ce n'est pas grave de laisser le compilateur en faire plus. Mais je crois que tu ne comprend strictement rien à ce que je défend. Je ne défend pas la disparition de mots clef comme const ou pure, mais de simplement ne pas les rendre « contaminant ».
    dans ce cas on peut dire que toi tu ne comprends pas ce que je dis. Tu prends encore l'exemple de quelqu'un qui ecrit du code quand je te demade de prendre l'exemple de quelqu'un qui lit du code.

  2. #142
    Membre éclairé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 264
    Points : 725
    Points
    725
    Par défaut
    Citation Envoyé par screetch
    mais je me sers beaucoup de const et je concois que quand on s'en sert pas on voit pas l'utilité (ou l'inverse). c'est aussi une des raisons pour laquelle je n'ai pas adheré a D.
    J'ai du mal à comprendre, tu parles du D d'il y a plusieurs années alors ? Parce que, pour ce que j'en sais, D possède const et pure depuis bientôt 3 ans... const en D est d'ailleurs beaucoup plus contraignant qu'en C++...
    "By and large I'm trying to minimize mentions of D in C++ contexts because it's as unfair as bringing a machine gun to a knife fight." - Andrei Alexandrescu

  3. #143
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par screetch Voir le message
    seul le linker permet de dire qu'une fonction sera pure ou non (car on a pas l'info sur les autres fonctions avant le linker). le code généré dépend de savoir si une fonction est pure ou non.

    si en théorie il est tout a fait possible de savoir si une fonction est pure ou non, en pratique cela se sait trop tard pour générer le code optimisé. ou alors il faut une phase d'optimisation globale qui s'éxécute encore apres le linker. pourquoi pas, mais bon.
    Je connais des compilo C++ qui permettent de marquer pure une fonction et comme tu dis une phase d'optimisation globale va optimiser deux appels avec les mêmes arguments par exemple. Au link.

    D'ailleurs en D le linker à moins de boulot. Pas besoin de virer des templates dupliqués quand tu compile toutes tes sources en même temps


    Citation Envoyé par screetch Voir le message
    mais je me sers beaucoup de const et je concois que quand on s'en sert pas on voit pas l'utilité (ou l'inverse). c'est aussi une des raisons pour laquelle je n'ai pas adheré a D.
    La constness en C++ a relativement peu d'utilité à mon avis par rapport à la surcharge cognitive qu'elle entraine (const * const, mutable, const_cast, constexpr).

    La const-correctness de D2 est bien différente. Elle vise à réparer le const C++ en le rendant transitif, répondre au besoin du constexpr C++1x, et permettre la parallélisation automatique.
    Tout celà au prix d'une plus grande complexité (const, immutable, shared...)

    D1 quant à lui à juste const qui a le rôle du constexpr de C++1x.


    Citation Envoyé par screetch Voir le message
    de meme, virtual, je prefere le dire moi meme plutot que de laisser le compilo le faire. c'est une documentation.
    Là je suis d'accord, je n'aime pas virtual par défaut parce que j'oublie parfois de préciser final et que DMD ne sait toujours pas dévirtualiser des fonctions pas surchargées (comme Java le ferait).

    Citation Envoyé par screetch Voir le message
    il ne faut pas oublier que l'on passe plus de temps a relire du code qu'a l'ecrire, et peut etre le compilateur D est plus malin que le compilateur C++ mais le programmeur D n'est pas plus malin que le programmeur C++ et pour moi le désamour du D vient du fait qu'il est plus difficile a relire (implémentation mélangée avec déclaration, impossible a la lecture de savoir quelle implementation d'une fonction sera appelée, impossible de savoir a la lecture si une fonction est pure ou const, ca fait beaucoup a "deviner")
    Ce que tu avances équivaut à dire que Java est moins lisible que C++. Je ne pense pas. Un langage est d'autant plus difficile à lire qu'on ne le connait pas.


    Là où en C++ je travaille sur des gros fichiers redondants, le D m'encourage a multiplier les petites classes qui ne font qu'une chose, dans des fichiers pas trop gros. Je trouve ça plus lisible.

    C'est vrai que les headers permettent d'avoir un apercu global d'un classe bien pratique, mais en D rien n'empêche de les générer ces headers.

    C'est un peu comme la différence entre Java et C++, à la différence que D:
    - ne propose pas une méta-programmation tronquée
    - n'a pas besoin de VM ni de Hotspot qui tourne en mémoire

    Citation Envoyé par screetch Voir le message
    en bref ces quelques defauts transforment selon moi un outil de codage en un outil de bidouillage pour les gens qui sont seuls sur leurs projets dans leur garage, en quelque sorte.
    Une attaque pas entièrement fausse.

    Mais si D reste obscur, ce n'est probablement pas à cause de ces supposés défauts là mais probablement à cause d'un leader pas aussi charimatique qu'un Larry Wall ou un Guido, et du manque de support d'un géant de l'industrie.

    En comparaison, quand Google sort Go, un langage à un stade d'avancement "là où était D il y a 7 ans" (dixit Alexandrescu), tous les bloggeurs de la planète ont une érection.

  4. #144
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Citation Envoyé par ponce Voir le message
    Là je suis d'accord, je n'aime pas virtual par défaut parce que j'oublie parfois de préciser final et que DMD ne sait toujours pas dévirtualiser des fonctions pas surchargées (comme Java le ferait).
    Attention de ne pas confondre les défauts du langage avec ceux du compilo

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    J'en conçoit bien l'utilité. seulement, dans la pratique, il y a un tas de trucs chiants qui n'ont pas lieu d'être avec le const. Comme souvent en C++, ce n'est pas l'idée qui est mauvaise, mais la mise ne pratique.

    Si je fait un accèsseur pour un donnée, du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A getX(){
        return this->x;
    }
    Si je l'appelle depuis un contexte ou this est const, je vais me faire appeler léon. Or, le compilo est tout à fait en mesure de "constifier" cette fonction. Je ne devrais avoir une erreur que si j'ai du code impliquant un non const dans getX.
    Tu réfléchis quelques peu à l'envers...

    Ici, si tu te fais appeler léon, tu n'a qu'à rendre ton accesseur constant, et le tour est joué...Mais...

    Imaginons plutôt une fonction quelconque "doSomething" qui prenne une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void MaClass::doSomething()
    {
        /* du code (ne modifiant rien) */
        laFonctionQuiAppelleUneFonctionModifiantLobjet();
        /*encore du code */
    }
    Il est impossible d'admettre que cette fonction ne modifie pas l'objet, car, même si c'est fait de manière indirecte (par appel d'une fonction qui appelle une fonction qui le modifie), le résultat est le même : l'objet est, bel et bien, modifié...

    Si tu invoque cette fonction dans un contexte ou this est constant, tu dois te faire rabrouer

    Permettre au compilateur de rendre une fonction constante en cas de besoin serait, peut-être, une bonne chose, mais cela risque fort de ne pas fonctionner à tous les coups: ton accesseur pourrait profiter de cette capacité, mais doSomething ne le pourrait pas.

    Dés lors, l'utilisateur pourrait très bien se trouver dans une situation dans laquelle deux instructions qui se suivent et dont la signature est strictement identique au niveau de la (non) constance seraient gérées différemment: acceptées pour l'accesseur, refusée pour doSomething .

    Cela ne facilite pas vraiment le boulot du programmeur

    D'autant plus que l'erreur apparaitrait sur doSomething, qui est, justement, la fonction pour laquelle il est le plus difficile de remarquer qu'il est impossible de faire en sorte qu'elle s'engage à ne pas modifier l'objet en cours.

    J'ai déjà fait part de mon avis sur le sujet: la règle de base doit être la moins restrictive possible et les restrictions doivent faire partie des règles particulières et être explicites

    Imagine la manière dont il faudrait énoncer la règle permettant de déterminer si une année est bissextile (une année est bissextile si elle est divisible par 4 sauf si elle est divisible par 100 mais elle l'est par contre si elle est divisible par 1000) si la règle générale avait été "toute année est bissextile par défaut", et tu comprendra ton malheur...
    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

  6. #146
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Imagine la manière dont il faudrait énoncer la règle permettant de déterminer si une année est bissextile (une année est bissextile si elle est divisible par 4 sauf si elle est divisible par 100 mais elle l'est par contre si elle est divisible par 1000) si la règle générale avait été "toute année est bissextile par défaut", et tu comprendra ton malheur...
    HS : chuchote @koala c'est par 400, pas par 1000 !
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  7. #147
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Permettre au compilateur de rendre une fonction constante en cas de besoin serait, peut-être, une bonne chose, mais cela risque fort de ne pas fonctionner à tous les coups: ton accesseur pourrait profiter de cette capacité, mais doSomething ne le pourrait pas.
    Bien sur ! La fonction ne sera pas toujours « constifiable ».

    Citation Envoyé par koala01 Voir le message
    Dés lors, l'utilisateur pourrait très bien se trouver dans une situation dans laquelle deux instructions qui se suivent et dont la signature est strictement identique au niveau de la (non) constance seraient gérées différemment: acceptées pour l'accesseur, refusée pour doSomething .
    Oui, sauf qu'ici, le compilo te renvoie dans les choux, non pas parce que tu as oublié de marquer const, mais bien parce qu'en effet, ta fonction n'est pas const. Ce qui me semble une bien meilleure raison.

    Si le message d'erreur est explicite, cela ne devrait pas poser de gros problèmes. S'il est important de spécifier explicitement le const, alors on peut aussi le faire.

    Je ne crois pas que l'exemple sur les années bissextiles soit très évident. Mais si tu veux aller dans ce sens, ce que je propose, c'est que le compilo se débrouille tout seul pour savoir si une années est bissextile ou non. Et qu'on puisse le spécifier si cela est réellement important (cela a alors valeur de contrat).

  8. #148
    Invité
    Invité(e)
    Par défaut
    Il me semble la politique pour const sera la-même que pour pure.

    Le programmeur devra spécifier si la fonction est const, et le compilateur le vérifiera derrière. Le const_cast sera possible toutefois.

  9. #149
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    Je ne crois pas que l'exemple sur les années bissextiles soit très évident. Mais si tu veux aller dans ce sens, ce que je propose, c'est que le compilo se débrouille tout seul pour savoir si une années est bissextile ou non. Et qu'on puisse le spécifier si cela est réellement important (cela a alors valeur de contrat).
    et je le redis, en temps que lecteur de code si je veux savoir si une fonction est const ou pas ? je compile dans ma tete?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    Je ne crois pas que l'exemple sur les années bissextiles soit très évident. Mais si tu veux aller dans ce sens, ce que je propose, c'est que le compilo se débrouille tout seul pour savoir si une années est bissextile ou non. Et qu'on puisse le spécifier si cela est réellement important (cela a alors valeur de contrat).
    Ce que cela a à voir, c'est qu'une règle générale se doit d'être... générale...

    Seules les exceptions ou les règles particulières peuvent se permettre d'être... particulières.

    Si tu commence à placer trop d'exceptions à la règle générale, c'est sans doute que ce que tu as considéré (visiblement à tord) dans un premier temps comme la règle générale était en réalité... une des exceptions

    En faisant en sorte que la constance doit être explicite, nous pouvons nous contenter d'une règle en trois points:
    1. une fonction peut être constante ou non
    2. toute fonction peut être invoquée au départ d'un objet donné sauf si
    3. <exception à la règle généale> l'objet en question est constant, auquel cas, seules les fonctions constantes peuvent être appelées.
    Si c'est la non constante qui devient implicite, et, surtout, si le compilateur doit être en mesure de déterminer si, oui ou non, une fonction peut être constante, tu auras beaucoup plus de mal à écrire des règles simples qui, en plus, permettent au lecteur du code de déterminer facilement s'il peut ou non invoquer telle ou telle fonction au départ d'un objet constant...

    D'où le parallèle avec les règles permettant de déterminer si une année est bissextile ou non: si tu pars d'une règle générale expliquant que toutes les années bissextiles, tu devra multiplier les exceptions à cette règle (et, partant, les exceptions aux exceptions), afin de coller à la réalité des faits
    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. #151
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Le const est loin d'être un cas particulier, et c'est bien le problème.

    Je comprend qu'on puisse vouloir faire les choses à la main quand on est capable de faire mieux que le compilo, mais quand on ne l'est pas ?

    Combien de fois on se tape des erreur de compilation car on a oublié un const (ou mis un de trop) ? Est-ce que cela est vraiment nécessaire sachant que ça peut se gérer automatiquement ?

    Et, question subsidiaire, pourquoi est-ce réellement important de savoir si ce qu'on appelle est const ou non ?

  12. #152
    screetch
    Invité(e)
    Par défaut
    tu reponds a une question par d'autres questions, c'est un peu agacant

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    Le const est loin d'être un cas particulier, et c'est bien le problème.
    Si c'est un cas particulier: tes objets sont non constants par défaut, et donc, par défaut, les fonctions qui ne s'engagent pas à ne pas modifier l'objet au départ duquel elles sont invoquées sont le cas général...

    Même si tu manipule, dans certaines parties de code, beaucoup d'objet constants, tu manipule quand même, de manière générale, encore beaucoup plus d'objet non constants
    Je comprend qu'on puisse vouloir faire les choses à la main quand on est capable de faire mieux que le compilo, mais quand on ne l'est pas ?
    Le problème n'est pas tant d'être capable ou non de faire mieux que le compilateur, le problème est de permettre au lecteur du code de le comprendre avec un maximum de facilité ou non...

    Un langage de programmation, quel qu'il soit, quel que soit le paradigme utilisé, n'est qu'un moyen qui nous est donné de nous faire comprendre à "quelque chose d'aussi bête qu'un ordinateur".

    S'il en avait été autrement, nous en serions restés depuis des décennies au langage machine.

    Mais la première qualité d'un code source, avant même de faire ce que l'on attend de lui, doit être d'être facilement compréhensible par l'humain, car il est beaucoup plus souvent lu qu'écrit ou modifié (write once read ever disent les anglo saxons...)

    Permettre au compilateur de déterminer "par lui même" si une fonction est (peut être considérée comme) constante ou non alors qu'il devient difficile pour l'humain de le déterminer lors de la lecture fait perdre cette qualité première.
    Combien de fois on se tape des erreur de compilation car on a oublié un const (ou mis un de trop) ?Est-ce que cela est vraiment nécessaire sachant que ça peut se gérer automatiquement ?
    Oui, sans hésiter...

    D'abord parce que cela permet au (re)lecteur du code de ne pas devoir (re)plonger dans plein de fonctions pour déterminer si une fonction appelée est bel et bien constante...

    Ensuite, parce qu'il vaut mieux une erreur de compilation qu'une erreur d'exécution...

    Tant qu'une erreur de compilation survient, tu ne perd "que" un peu de temps à la résoudre...

    Lorsqu'une erreur d'exécution survient en présentation, il faut s'appeler microsoft pour que cela passe inaperçu voire normal
    Et, question subsidiaire, pourquoi est-ce réellement important de savoir si ce qu'on appelle est const ou non ?
    Parce qu'il arrive que tu ne veuille absolument pas qu'un objet (passé par référence, par exemple) soit modifié...

    De trop nombreux résultats erronés ou aberrants (quand ce ne sont pas des plantages magistraux) sont dus au fait qu'une modification a été apportée à un objet alors qu'elle n'avait pas lieu d'être.

    Le respect de la constance (la "const correctness") t'oblige, effectivement, à réfléchir plutôt deux fois qu'une à ce que tu fais, mais te permet, en retour, d'éviter bien des déboires qui, la loi de murphy aidant, ne se feront jour qu'au pire moment que tu pourra imaginer
    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

  14. #154
    Membre régulier Avatar de smatador
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Points : 78
    Points
    78
    Par défaut
    Pour ma part j'ai tendance à croire que l'élément décisif pour qu'un langage puisse s'imposer reposait moins sur ses qualités intrinsèques que sur la qualité de son écosystème (EDI, bibliothèques, outils...). Cela suppose des investissements importants, en hommes et en ressources, que seules de grosses compagnies peuvent aujourd'hui se permettre. D'ailleurs il n'est pas étonnant que les derniers langages à avoir réussi à percer "récemment" (Java, C#) sont issus de telles organisations.

    Personnellement j'ai de sérieux doutes qu'en à la capacité du D à percer, je pencherai plutôt sur le langage GO de Google (même si ce dernier est, à l'heure actuelle, loin d'être parfait).

  15. #155
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    Je comprend qu'on puisse vouloir faire les choses à la main quand on est capable de faire mieux que le compilo, mais quand on ne l'est pas ?
    Afin d'être certain de bien comprendre ce que tu entends par laisser faire le compilo, je voudrait reformuler ce que j'ai cru comprendre :
    On peut déclarer une fonction const. A ce moment, elle va vérifier :
    - Qu'elle ne modifie rien directement
    - Qu'elle n'appelle que des fonction déclarées comme const ou des fonction non déclarées comme const, mais qui sont const quand même (c'est à dire qui ne provoqueraient pas d'erreur de compilation si on les déclarait const elles aussi).

    C'est bien ça ?

    Si oui, quelques questions :
    - Comment faire pour les cas où le const permet de choisir entre deux fonctions surchargées, ça ne pose pas de problème de mauvaise fonction appelée si un const est omis ?

    - Pour que ce système puisse marcher, il faut un système de compilation moins séparé qu'en C++, où pour appeler une fonction, il faut non seulement avoir sa déclaration, mais aussi des informations complémentaires ajoutées par le compilateur. N'est-ce pas problématique ? Comme de plus ces informations dépendent de l'implémentation d'une fonction, modifier une implémentation peut demander à recompiler plein de code. Comment est-ce géré ?

    Citation Envoyé par deadalnix Voir le message
    Combien de fois on se tape des erreur de compilation car on a oublié un const (ou mis un de trop) ? Est-ce que cela est vraiment nécessaire sachant que ça peut se gérer automatiquement ?
    Non, mais de bon outils peuvent améliorer la situation, en signalant ces erreurs en cours de frappe, sans passer par un cycle de compilation complet.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #156
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Citation Envoyé par koala01 Voir le message
    D'abord parce que cela permet au (re)lecteur du code de ne pas devoir (re)plonger dans plein de fonctions pour déterminer si une fonction appelée est bel et bien constante...

    Ensuite, parce qu'il vaut mieux une erreur de compilation qu'une erreur d'exécution...
    S'il est aussi important de le savoir à la relecture, c'est justement pour éviter de se manger une erreur de compil dans les dents.

    Le seul moment ou il est justifié de spécifier const, c'est s'il y a un traitement différent à faire. Tout le reste n'est que complexité inutile, et pas qu'a l'écriture.

    EDIT, car on a posté en même temps :

    Citation Envoyé par JolyLoic Voir le message
    On peut déclarer une fonction const. A ce moment, elle va vérifier :
    - Qu'elle ne modifie rien directement
    - Qu'elle n'appelle que des fonction déclarées comme const ou des fonction non déclarées comme const, mais qui sont const quand même (c'est à dire qui ne provoqueraient pas d'erreur de compilation si on les déclarait const elles aussi).

    C'est bien ça ?
    Oui, c'est exactement ça.

    Citation Envoyé par JolyLoic Voir le message
    Si oui, quelques questions :
    - Comment faire pour les cas où le const permet de choisir entre deux fonctions surchargées, ça ne pose pas de problème de mauvaise fonction appelée si un const est omis ?
    Le compilo doit « constifier » au maximum.

    Citation Envoyé par JolyLoic Voir le message
    - Pour que ce système puisse marcher, il faut un système de compilation moins séparé qu'en C++, où pour appeler une fonction, il faut non seulement avoir sa déclaration, mais aussi des informations complémentaires ajoutées par le compilateur. N'est-ce pas problématique ? Comme de plus ces informations dépendent de l'implémentation d'une fonction, modifier une implémentation peut demander à recompiler plein de code. Comment est-ce géré ?
    Pour la compilation : non, ce n'est pas un problème. C'est fait en java par exemple. Pire, en java le chargement dynamique de code est possible, ce qui nécessite de faire ce genre d'opérations en « live » pendant l'exécution du programme. En fait, il faut que le compilateur place des tags dans les objets, et que le linker finalise des bouts de code en fonction.

    Pour les cas des DLL par exemples, c'est typiquement le genre de cas ou il faut spécifier ce genre de truc explicitement. Sinon pour le reste, avec des fichier objets bien foutus, c'est le linker qui prend en charge le tout, donc pas de recompilation nécessaire.

    De la même façon que pour la purification, les algo mis en jeux s'exécutent très rapidement.

  17. #157
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Bonjour,
    personnellement je suis tout à fait d'accord avec la FAQ, sur le fait qu'une classe doit se construire plutôt de l'extérieur que de l'intérieur. Or le fait de laisser le compilateur décider de la constance d'un méthode, cela revient à laisser l'implémentation définir l'interface (soit tout l'opposé ).

    De plus, le const signifie que la fonction ne modifie pas l'objet dans son concepte. Une fonction peut très bien ne pas modifier un objet en apparence (c'est-à-dire que l'on aurait pu la marquer const sans que cela n'empèche la compilation), alors que son action modifie tout de même "l'état" de l'objet.
    Vite un exemple, car dit comme ça c'est assez obscure :
    pour un conteneur type vecteur, qui implémente une sémantique de valeur, une fonction Elt_t & operator[](size_t Index) non const pour très bien être marquée comme telle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class vect_t
    {
    private:
       Elt_t * m_TabElt;
    // ...
    // allocation et désallocation de m_TabElt   
    // ...
       Elt_t & operator[](size_t Index) // const ?
    // pourrait être marqué const tout en renvoyant une référence non const !
    // néanmoins cela trahirait le comportement attendu de l'objet 
       {
    	return  *(m_TabElt + Index);
       }
    };
    Si le compilateur décidait, il la considérerait à tort const ...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par deadalnix Voir le message
    S'il est aussi important de le savoir à la relecture, c'est justement pour éviter de se manger une erreur de compil dans les dents.
    ...Ou pour mettre une erreur de conception en évidence...

    Si tu détermines, à un moment donné qu'un objet n'a aucune raison d'être modifié mais qu'un appel de fonction modifie cet objet, que ce soit de manière directe ou indirecte, c'est que tu as, très clairement, "foiré" ta conception quelque part

    Si tu laisse le compilateur gérer la constance des fonctions, et que, pas de bol, il n'arrive pas à rendre une fonction constante du fait des appels impliqués, non seulement tu perds, comme je l'ai déjà signalé, la qualité première du code, mais, en plus, tu te mangera une erreur à l'exécution, ce qui est encore bien pire que si c'était "simplement" une erreur de compilation.
    Le seul moment ou il est justifié de spécifier const, c'est s'il y a un traitement différent à faire. Tout le reste n'est que complexité inutile, et pas qu'a l'écriture.
    Non, il est justifié de le faire chaque fois que ton analyse et ta conception mettent clairement en évidence que l'objet n'a pas lieu d'être modifié...

    Commence par te demander pourquoi tu pourrais vouloir rendre un objet constant...

    La raison principale est, sans doute, que tu veux le passer en argument à une fonction en évitant la copie de l'objet, mais que tu souhaites qu'il ne soit pas modifié par la fonction que tu appelles...

    Pour éviter la copie, tu n'as pas beaucoup le choix, tu passera sans doute l'objet par référence comme paramètre à la fonction appelée.

    Le fait de le passer sous la forme d'une référence aura d'autres avantages qui sortent largement du débats, et que je ne citerai donc pas ici

    Pour éviter tout risque que la fonction appelée ne modifie l'objet, tu le passera sous la forme d'une... référence constante.

    Le fait de passer un argument sous la forme d'une référence constante a un autre avantage: celui de permettre l'utilisation d'une variable temporaire non nommée.

    Une variable temporaire non nommée est une variable qui ne porte aucun nom dans la fonction appelante, dont on n'a besoin que le temps de l'appel de la fonction, et donc, à laquelle il sera impossible d'accéder en dehors de la fonction appelée.

    Comme Il est impossible d'accéder à cette variable dans la fonction appelante, il n'y a aucun sens à en permettre la modification.

    C'est le phénomène que l'on observe avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /* soit la fonction */
    void foo(std::string const & str)
    {
        /* code utilisant str */
    }
    void bar()
    {
        foo("bonjour"); //création d'une variable temporaire non nommée de type
                        // std::string contenant "bonjour"
    }
    grâce à la présence d'un constructeur non explicite dans la classe std::string prenant un const char * en argument (selon l'exemple) et agissant comme... opérateur de conversion de const char * en std::string.

    Comme une variable temporaire non nommée n'existe que le temps de l'appel de la fonction et qu'il est impossible d'y accéder depuis la fonction appelante, il n'y a strictement aucun intérêt à en permettre la modification dans la fonction appelée...

    C'est la raison pour laquelle la manoeuvre est autorisée pour... les références constante (permettant, par ailleurs, d'éviter la copie si l'objet passé en argument n'est pas une variable temporaire non nommée).

    La deuxième raison qui pourrait t'inciter à employer la constance réside, même si je n'aime pas à y avoir recours, dans la définition d'accesseurs...

    En effet, lorsque tu définis un accesseur sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Type MaClass::getX()
    {
        return m_x;
    }
    tu obtiens, encore une fois, une copie de m_x, avec, encore une fois, tous les problèmes liés au fait qu'il y a copie (nécessité que Type soit copiable, utilisation parfois massive de mémoire, temps de copie parfois excessif, ...)

    La solution au seul problème de copie est donc, encore une fois, de renvoyer le membre par référence, mais, si tu renvoie une référence non constante, un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(MaClass const & c)
    {
       c.getX()=Type("salut");
    }
    aura pour résultat... la modification de l'objet en cours (c, dans l'exemple)...

    Ce qui risque fort de poser problème vu que foo n'est pas sensée modifier c...

    Et, pour notre malheur, un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void foo(MaClass const & c)
    {
       c.getX().getY().getMachinChose() = TypeMachinChose(342);
    }
    (getX, getY et getZ renvoyant des objets de types différents sous la forme de références)

    pourrait être tout à fait valide si ni les références renvoyées par getX, getY et getMachinChose, ni les dites fonctins n'étaient constantes...

    Mais nous aurions alors modification de ce qui est renvoyé par getMachinChose qui, fatalement, signifie la modification de ce qui est renvoyé par getY, qui implique la modification de ce qui est renvoyé par getX... qui implique la modification de... c...

    Si tu laisse faire le travail au compilateur, il y a une chance sur deux pour... qu'il accepte le code en utilisant la version non constante de getX, getY et getMachinChose et une chance sur deux... pour qu'il la refuse...

    S'il la refuse, tu aura, de toutes manières, une erreur de compilation, mais, s'il l'accepte, tu risques, au mieux, d'avoir des résultats finaux aberrants...

    Si, dés le départ, le lecteur du code voit que getX renvoie... une référence constante, il saura qu'il ne peut pas modifier ce qu'elle renvoie, de même pour getY et getMachinChose.

    Il saura donc qu'il ne peut pas décider de modifier ce qui est renvoyé par getMachinChose.

    De leur coté, la constance des fonctions getX, getY et getMachinChose assurent la cohérence au niveau des différents objets renvoyés:

    A partir du moment où une des fonctions sera déclarée constante, nous seront surs que le compilateur nous enverra paitre si, pour une raison ou une autre, les fonctions membres invoquées au départ de l'objet renvoyé ne prennent pas, elles-aussi, l'engagement de ne pas modifier l'objet en cours...

    Encore une fois, nous pourrions dire que le compilateur pourrait déduire la constance de la fonction (ce qui, ici, nécessiterait sans doute de connaitre l'implémentation des fonctions getX, getY et getMachinChose...), sauf que, non seulement, nous perdons, ici encore, la qualité primordiale du code, mais, en plus, il risque de considérer à tord les différentes fonctions comme étant... non constantes...

    Ce à quoi je veux en venir, c'est que, si même on venait (quelle horreur) à s'en foutre le la première qualité d'un code, il serait excessivement dangereux de s'en remettre au compilateur pour déterminer l'engagement que prend (ou non) une fonction à ne pas modifier l'objet en cours...
    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

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par gb_68 Voir le message
    De plus, le const signifie que la fonction ne modifie pas l'objet dans son concepte. Une fonction peut très bien ne pas modifier un objet en apparence (c'est-à-dire que l'on aurait pu la marquer const sans que cela n'empèche la compilation), alors que son action modifie tout de même "l'état" de l'objet.
    C'est la raison de l'existence du mot clé mutable lorsqu'il s'agit de gérer un "cache" ne devant être remis à jour que sous certaines conditions...

    C'est plus ou moins le phénomène que l'on peut rencontrer dans une liste:
    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
    class List
    {
        public:
            void addItem()
            {
                /* insertion de l'élément*/
                modified_=true;
            }
            size_t size() const
            {
                if(modified)
                {
                    size_=0;
                    Element * temp =first_;
                    while(temp)
                    {
                        ++size_;
                        temp=temp->next;
                    }
                }
                modified_=false;
                return size_;
            }
        private:
            Element * first_;
            mutable size_t size_;
            mutable bool modified_;
    };
    size_ (selon l'exemple) n'est recalculé que si l'objet a été modifié depuis le dernier appel à... size
    Vite un exemple, car dit comme ça c'est assez obscure :
    pour un conteneur type vecteur, qui implémente une sémantique de valeur, une fonction Elt_t & operator[](size_t Index) non const pour très bien être marquée comme telle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class vect_t
    {
    private:
       Elt_t * m_TabElt;
    // ...
    // allocation et désallocation de m_TabElt   
    // ...
       Elt_t & operator[](size_t Index) // const ?
    // pourrait être marqué const tout en renvoyant une référence non const !
    // néanmoins cela trahirait le comportement attendu de l'objet 
       {
    	return  *(m_TabElt + Index);
       }
    };
    Si le compilateur décidait, il la considérerait à tort const ...
    J'aurais même encore fait plus simple pour cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       Elt_t & operator[](size_t Index) // const ?
    // pourrait être marqué const tout en renvoyant une référence non const !
    // néanmoins cela trahirait le comportement attendu de l'objet 
       {
    	return m_TabElt[index];
       }
    Mais ce n'est qu'un détail
    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

  20. #160
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ce à quoi je veux en venir, c'est que, si même on venait (quelle horreur) à s'en foutre le la première qualité d'un code, il serait excessivement dangereux de s'en remettre au compilateur pour déterminer l'engagement que prend (ou non) une fonction à ne pas modifier l'objet en cours...
    Le compilo n'est pas la pour gérer l'engagement. Il est la pour dire « mon programmeur n'a pas marqué ceci comme const, mais en fait ça l'est, ne lui renvoyons pas une erreur dans les gencives et compilons quand même ».

    Tu donnes de bons exemples ou il est utile de spécifier explicitement le const. le soucis, c'est que pour que tout cela fonctionne bien, il va falloir par la suite que je colle du const partout dans mon programme, et j'ai pas mal de chance d'avoir à un moment ou a un autre à me battre avec.

    Ce que tu mets en valeur, c'est que ce qui est dangereux, c'est la « déconstification ».

    Ce que je propose, c'est que :
    1/ Les choses soient non const par defaut (cas générique). Le compilo de décider de « constifier » si cela l'est dans la pratique.
    2/ Il est possible de spécifier explicitement que quelque chose est const. Dans ce cas, le compilo est chargé de vérifier que la contrat est bien respecté.

Discussions similaires

  1. [langage] Je cherche un bon livre ?
    Par Anonymous dans le forum Langage
    Réponses: 13
    Dernier message: 09/04/2003, 13h16
  2. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52
  3. [langage] comment créer des fichiers ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 05/05/2002, 16h33
  4. Comparer des fichiers de données : Quel Langage ?
    Par Anonymous dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 24/04/2002, 22h37
  5. Cours, tutoriels, logiciels, F.A.Q,... pour le langage SQL
    Par Marc Lussac dans le forum Langage SQL
    Réponses: 0
    Dernier message: 04/04/2002, 10h21

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