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 :

Eviter une syntaxe trompeuse.


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut Eviter une syntaxe trompeuse.
    Bonsoir.

    Supposons qu'on ait défini une classe MonTypeNumerique qui admette un constructeur de conversion à partir du type (intégré, mais peu importe) int.

    L'utilisateur peut alors écrire des choses comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int j = 3;
    MonTypeNumerique MonNombre = j;
    (Si je ne me trompe, c'est le constructeur de conversion qui intervient dans cette syntaxe, une surdéfinition de l'opérateur = n'a rien à voir ici.)

    Bon, vous allez peut-être trouver ça futile, mais je n'aime pas la syntaxe de la seconde ligne du code ci-dessus, il me semble qu'elle risque de faire perdre de vue à l'utilisateur que les deux membres ne sont pas du même type.
    J'aimerais donc mieux que l'utilisateur soit obligé d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    MonTypeNumerique MonNombre(j);
    ou peut-être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    MonTypeNumerique MonNombre = MonTypeNumerique(j);
    J'aimerais savoir s'il est possible d'empêcher la syntaxe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MonTypeNumerique MonNombre = j;

    Merci d'avance pour les réponses.

    M.

  2. #2
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    non, ce n'est pas possible, c'est une des caractéristique de C++, appeler = à la construction appele le constructeur... au lieu de l'opérateur =...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par Swoög
    non, ce n'est pas possible, c'est une des caractéristique de C++, appeler = à la construction appele le constructeur... au lieu de l'opérateur =...
    Merci de la réponse.
    Je me demande si je suis le seul que cela met mal à l'aise...

    M.

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Déclare ton constructeur avec le mot-clé explicit, c'est fait pour ça. Par contre effectivement je ne suis pas certain du comportement dans ce cas.

  5. #5
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Perso, je me suis fait avoir par la syntaxe aussi... beaucoup confonde (suffit de parcourir un peu le forum pour s'en rendre compte)

    et c'est vrai que c'est un peu pénible... Mais bon, C++ a aussi été créé dans une optique pratique, et non théorique...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonType MaVar2 = MaVar1;
    est plus lisible (car plus aéré) que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonType MaVra2(MaVar1);
    donc...

    Mais c'est vrai que c'est un peu pénible parfois
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  6. #6
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Citation Envoyé par Laurent Gomila
    Déclare ton constructeur avec le mot-clé explicit, c'est fait pour ça.

    Je croyais que ça c'était uniquement pour éviter les conversions implicites !?
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par Laurent Gomila
    Déclare ton constructeur avec le mot-clé explicit, c'est fait pour ça. Par contre effectivement je ne suis pas certain du comportement dans ce cas.
    J'ai déclaré le constructeur "explicit" et, en effet, la syntaxe qui me déplaît est maintenant refusée par le compilateur.

    J'avais lu, en son temps, ce qui concerne "explicit", mais je n'en avais sans doute pas compris l'intérêt à l'époque.

    Merci beaucoup.

    M.

  8. #8
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Ca fait un peu effet de bord d'explicit: les convertions implicites ne sont plus possibles. La syntaxe de construction avec "=" est assimilée à la construction avec convertion implicite.

    Quand à beurk! Dans la catégorie syntaxe trompeuse, c'est pas mal. On paie une construction d'initialisation plus une construction de recopie.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par Luc Hermitte
    Ca fait un peu effet de bord d'explicit: les conversions implicites ne sont plus possibles.
    Pourquoi "effet de bord" ? Nest-ce pas à cela qu'explicit sert ?

    La syntaxe de construction avec "=" est assimilée à la construction avec conversion implicite.
    Pas si les deux membres ont le même type, je suppose. Alors le constructeur de copie n'est pas obligé de recourir à une conversion implicite et la construction par "=" fonctionne. (Sauf erreur, c'est essentiellement le constructeur de copie qui intervient dans une construction par "=".)

    Quant à beurk! Dans la catégorie syntaxe trompeuse, c'est pas mal. On paie une construction d'initialisation plus une construction de recopie.
    Les compilateurs ne pourraient-ils pas optimiser ça ?

    M.

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par Luc Hermitte
    Quand à beurk! Dans la catégorie syntaxe trompeuse, c'est pas mal. On paie une construction d'initialisation plus une construction de recopie.
    Une construction de recopie ou d'affectation ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Même si certains le font, ils ne le font pas tous.
    En gros, ce n'est pas du tout une habitude qu'il faut prendre.
    explicit sert en effet à ça. Beaucoup de géants du C++ conseillent de déclarer les constructeurs "de conversion" explicit d'ailleurs.

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    C'est en effet un réflexe à avoir.
    Encore que, cela dépend aussi du contexte.

    Pour moi, on met un constructeur en explicit par défaut, puis on vois si on peut se permettre de l'enlever...

    Des constructeurs que j'ai tendance à rendre implicites, ce sont ceux d'une union que je passe en paramètre d'une fonction.
    (union qui n'est généralement jamais instanciée ailleurs).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par Médinoc
    Une construction de recopie ou d'affectation ?
    A mon avis, de copie. Quand on crée un objet à l'aide de "=", ce n'est pas l'opérateur d'affectation qui intervient, mais le constructeur de copie.
    On peut s'en assurer en faisant par exemple envoyer des messages différents par le constructeur de copie et l'opérateur d'affectation.

    M.

  14. #14
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    En effet.
    Quand on utilise = à la déclaration de l'objet, c'est une copie.
    Sinon, c'est une affectation.

  15. #15
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Citation Envoyé par Mersenne
    [blocage de la construction avec =]Pourquoi "effet de bord" ? Nest-ce pas à cela qu'explicit sert ?
    Je trouve que cela sert avant tout à empécher:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct Toto {
        explicit Toto(int);
    };
     
    f(Toto const&);
    ...
    f(42);
    J'assimile la construction avec = essentiellement à un sucre syntaxique. Il y a peut-être des cas où la méta-prog change la donne, je ne sais pas.

    Pas si les deux membres ont le même type, je suppose. Alors le constructeur de copie n'est pas obligé de recourir à une conversion implicite et la construction par "=" fonctionne. (Sauf erreur, c'est essentiellement le constructeur de copie qui intervient dans une construction par "=".)
    Si les deux membres ont le même type effectivement, ce n'est plus une construction de convertion, mais une construction de recopie. Ici, l'explicit empêche le recours au sucre syntaxique.



    Les compilateurs ne pourraient-ils pas optimiser ça ?
    Possible, mais pas certain. Si je me souviens bien, SunWSPro, qui m'a déjà agréablement surpris avec les RNVO, ne fait pas .

    Sinon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    T v(42); // appel explicite au constructeur de convertion
    T w = 42; // appel implicite au constructeur de convertion
    T u(v); // appel explicite au constructeur de recopie
    T t = v; // appel implicite au constructeur de recopie
    t = w; // appel à l'opérateur d'affectation
    T z = T(42); // appel explicite au constructeur de convertion suivi d'un appel implicite au constructeur de recopie
    T zz(T(42)); // pareil, mais tout en explicite.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Merci pour vos réponses, Luc Hermitte.

    J'avais été étonné quand vous disiez que "explicit" empêche la construction par "=", mais j'ai fait des essais avec Visual C++ 6 et ils vous donnent raison, même quand l'objet figurant à droite de "=" est du même type que l'objet à créer.

    Dans ce cas, je reçois le message suivant :
    error C2440: 'initializing' :
    // cannot convert from 'class MaClasseExplicit' to 'class MaClasseExplicit'
    // No copy constructor available for class 'MaClasseExplicit'

    Pourtant, j'ai bel et bien défini un constructeur de copie.

    En revanche, quand les constructeurs ne sont pas déclarés "explicit", il me semble que

    MaClasse MonObjet = X

    revient toujours à

    MaClasse MonObjet(X)

    ce qui est conforme à votre dernier message.

    Il me semble que les manuels ne sont pas très bavards sur le "=" d'initialisation...

    M.

  17. #17
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Les compilateurs ne pourraient-ils pas optimiser ça ?
    Possible, mais pas certain. Si je me souviens bien, SunWSPro, qui m'a déjà agréablement surpris avec les RNVO, ne fait pas .
    En C++0x cela fera appel au constructeur de déplacement.

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par loufoque
    En C++0x cela fera appel au constructeur de déplacement.
    J'avoue que je n'avais jamais entendu parler des constructeurs de déplacement.

    Google ne donne rien sous "constructeur de déplacement" et ce qu'il donne sous "displacement constructor" ne concerne que la théorie générale de la compilation.

    Pour "moving constructor", j'ai trouvé ceci sur un forum :
    "The reason is that C++ is missing ``moving constructors''
    which are like copy constructors with the difference that the source object is no longer needed afterwards. A moving constructor can often be significantly faster than a copy constructor."

    (On dit aussi "move constructor".)

    Quelqu'un pourrait-il illustrer par un exemple l'intérêt des constructeurs de déplacement ? Merci d'avance.

    M.

  19. #19
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    J'avoue que je n'avais jamais entendu parler des constructeurs de déplacement.
    Normal, ça existe pas encore, c'est dans la prochaine version de C++.
    Tu peux appeler ça constructeur de mouvement si tu veux, moi je trouve que ça sonne bizarre.

    Quelqu'un pourrait-il illustrer par un exemple l'intérêt des constructeurs de déplacement ? Merci d'avance.
    Il n'est pas nécessaire de faire des copies profondes pour les données se trouvant sur la mémoire libre (le tas).
    Copier un std::vector nécessite de copier toutes les données qu'il contient, alors que le déplacer ne nécessite que de copier le pointeur vers ces données.

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2006
    Messages : 107
    Par défaut
    Citation Envoyé par loufoque
    Tu peux appeler ça constructeur de mouvement si tu veux, moi je trouve que ça sonne bizarre.
    Je n'ai rien contre l'expression "constructeur de déplacement", je voulais simplement permettre à ceux qui auraient voulu chercher par Google de perdre un peu moins de temps.


    Il n'est pas nécessaire de faire des copies profondes pour les données se trouvant sur la mémoire libre (le tas).
    Copier un std::vector nécessite de copier toutes les données qu'il contient, alors que le déplacer ne nécessite que de copier le pointeur vers ces données.
    Merci de la réponse.

    On verra des exemples de code quand ce sera intégré.

    M.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Formulaire] eviter une revalidation
    Par eleve36 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 28/10/2005, 11h29
  2. [DB2] Eviter une cascade infini dans un trigger
    Par Fatah93 dans le forum DB2
    Réponses: 2
    Dernier message: 25/04/2005, 14h23
  3. [langage] comprendre une syntaxe particulière
    Par mat21 dans le forum Langage
    Réponses: 4
    Dernier message: 08/12/2004, 18h12
  4. Réponses: 2
    Dernier message: 21/06/2004, 15h55
  5. [RICHEDIT] -> Coloriser une syntaxe ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 6
    Dernier message: 18/01/2004, 12h57

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