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 :

[POO] Méthodes virtuelles const ?


Sujet :

C++

  1. #1
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut [POO] Méthodes virtuelles const ?
    Voila, il est plus de minuit et demi maintenant et je me pose une question existencielle :

    Les méthodes d'interface et autres méthodes virtuelles "ont-elles le droit" d'être déclarées const?

    A moins de cas particuliers, mais je n'en vois pas, même en cherchant, c'est à l'implémentation de décider si, oui ou non, la méthode redéfinie va être amenée à modifier l'objet.

    Quel est votre avis la-dessus ?

  2. #2
    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 : 48
    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
    Oui, elles en ont le droit. Être const fait partie du contrat, et c'est la classe de base qui fixe le contrat. C'est elle qui dit qu'une fonction aura N paramètres de tels ou tels types, c'est aussi elle qui dit si on pourra l'appeler sur un objet constant.
    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.

  3. #3
    Alp
    Alp est déconnecté
    Expert éminent sénior

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

    Informations forums :
    Inscription : juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Exemple "bête" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class GraphicObject
    {
      public :
        virtual void Draw() const = 0;
    };
     
    class Ball : public GraphicObject
    {
      public : 
        void Draw() const { /* on affiche la balle */ }
    }
    La méthode Draw ne modifiant pas l'instance, on peut la "const-qualifier", et ainsi elle pourra être appelée sur des objets constants, tout en préservant le polymorphisme désiré.

  4. #4
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut
    Bonjour,

    si j'écris ton exemple tel quel, Alp, j'ai l'erreur "cannot instanciate abstract class" car la méthode Draw de Ball n'est justement pas const alors que celle GraphicObject est déclarée comme l'étant.

    Et c'est bien là le fond du problème. Je suis tout à fait d'accord avec vous pour dire que décider de rendre une méthode virtuelle const établi un contrat qui doit suivre une logique et que cela doit être fait lors du design de la classe abstraite de base.
    Seulement je trouve pleins de cas où cela pose problème.

    Si je reprends l'exemple de l'objet graphique et sa méthode Draw() : l'objet est dans un certain état (position, couleur etc.) et on lui demande de s'afficher en l'état, à priori sans le modifier, de façon à ce que si l'on appelle à nouveau cette méthode juste derrière, le même affichage devrait nous être donné. Donc notre méthode est const vis à vis de l'objet graphique.

    Alp, tu as surement raisonné ainsi et j'aurais certainement fait pareil. Mais toujours en continuant l'exemple, imaginons que j'implémente ObjetGraphique et mon implémentation nécessite beaucoups de précalculs non négligeables avant de pouvoir effectivement se dessiner. Ces calculs dépendent de l'état de l'objet et ne devraient pas avoir à être ré-éxécutés si l'état n'a pas changé depuis le dernier appel à Draw(). Et bien, à part en déclarant des variables mutable, je ne peux pas sauver mes précalculs dans Draw().

    Voilà ce qui me chiffone depuis hier.

  5. #5
    Alp
    Alp est déconnecté
    Expert éminent sénior

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

    Informations forums :
    Inscription : juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    En fait j'ai simplement oublié le const...

    Car j'étais fatigué

    Mais tu peux pas casser la qualification const, effectivement. J'édite le code ci-dessus

  6. #6
    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 : 48
    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 NiamorH Voir le message
    imaginons que j'implémente ObjetGraphique et mon implémentation nécessite beaucoups de précalculs non négligeables avant de pouvoir effectivement se dessiner. Ces calculs dépendent de l'état de l'objet et ne devraient pas avoir à être ré-éxécutés si l'état n'a pas changé depuis le dernier appel à Draw(). Et bien, à part en déclarant des variables mutable, je ne peux pas sauver mes précalculs dans Draw().
    Et justement, tu peux les déclarer mutable, et alors, ça marche. Je ne vois pas trop ce qui te gène dans ce cas.

    Et le mutable n'est pas là "pour faire plaisir" à la classe de base : Il est là parce que, indépendamment de toute autre chose, ton objet n'est pas sémantiquement modifié par son affichage, le fait qu'il y ait des pré-calculs mis en cache n'étant qu'un détail d'implémentation ne devant pas apparaître dans l'interface.
    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.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 326
    Points : 41 366
    Points
    41 366
    Par défaut
    Pour moi, un truc qui "aide" à comprendre les variables mutables, c'est de se dire que ce ne sont pas des variables à part entière de la classe, juste des détails d'implémentation.
    Ce qui est le cas pour la plupart des utilisations de variables mutables: Comptage de références intrusif, cache, et compteurs d'appels...
    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.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 591
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 591
    Points : 30 483
    Points
    30 483
    Par défaut
    Salut,

    Le role d'une méthode const est de préciser au compilateur "cette méthode ne modifie pas l'objet".

    Par le fait de modifier l'objet, il faut comprendre le fait de modifier les "propriétés intrinsèques" qui font que ta balle rouge et bleue d'un diametre de N n'est pas une balle verte et jaune d'un diamètre de 2N, et que, au moment de l'appel, sa position et son "orientation" (le fait que le rouge soit en haut à gauche et le bleu en bas à droite) se seront pas modifiée.

    Par contre, si pour t'éviter d'avoir à recalculer en permanence l'aspect à donner à ta balle, tu décide de mettre cet aspect dans un cache, tu te trouve exactement dans le cas d'utilisation d'une variable mutable: ca ne modifie absolument pas les propriétés intrinsèques de la balle, cela ne modifie que la manière dont la méthode d'affichage va représenter la balle dans la situation donnée.
    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

  9. #9
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut
    Effectivement, le mot clef mutable est la solution que j'utilise. Mais ça m'a toujours géné d'y avoir recours. Dans ma tête je me suis toujours dis "tu as dû mal penser quelque chose pour en arriver à devoir t'en servir."

    Peut être que je me fais du mauvais sang pour rien après tout.

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

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 326
    Points : 41 366
    Points
    41 366
    Par défaut
    Je me disais la même chose au début, c'est d'ailleurs pourquoi j'ai restreint mon utilisation de mutable au comptage de références intrusif et aux caches...
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 591
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 591
    Points : 30 483
    Points
    30 483
    Par défaut
    Effectivement, tu te fais beaucoup de mauvais sang pour rien...

    Bien sur, comme beaucoup de choses en programmation, il faut toujours se poser la question de savoir si oui ou non il est opportun de déclarer un membre mutable...

    Bien sur, l'abus de déclaration de membres mutables est au minimum le signe d'une réflexion sans doute erronée.

    Mais, une fois que tu a clairement défini qu'un membre agit comme un cache, comme une machine à état qui peut devenir invalide à n'importe quel moment (y compris au sein de méthodes constantes), et que la modification de ce membre ne modifie en rien les "propriétés intrinsèques" de l'objet en cours, tu es clairement dans le cadre dans lequel il est "opportun" de déclarer le membre mutable
    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

  12. #12
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut
    Oui mais c'est aussi parce qu'on est parti d'un exemple qui s'y prétait déjà bien : la balle se dessine et met à jour un cache de précalculs pour la fois suivante. Le cache n'a d'utilité que pour cette méthode Draw(), au pire une ou deux autres méthodes de l'objet, ok je passe mon cache en mutable, c'est bateau.

    Je vous donne un autre exemple, toujours fictif bien que très inspiré, où cette fois c'est beaucoup moins évident.

    Mon programme est un lecteur audio style winamp. J'ai une classe Lecteur qui dispose d'une propriété "Position" permettant de savoir à tout moment où en est la lecture.
    La mise à jour de Position déclenche un évènement qui demande à l'interface de rafraîchir la barre de progression de la piste audio.

    La classe Lecteur implémente l'interface IDataFiller permettant au moteur audio de démander régulièrement des échantillons à envoyer à la carte son. La signature de la méthode à implémenter est : void Fill( char* data, size_t dataSize ) const.
    Le lecteur attentif aura remarqué le fameux const

    A priori tout ce qu'est sensé faire le DataFiller (mon Lecteur) c'est de remplir un buffer, donc, pas de souci, la méthode est en droit d'être const.
    Seulement le Lecteur veut également en profiter pour mettre à jour la propriété Position parce que, après tout, il a avancé dans la lecture.

    Résultat : J'ai une propriété tout à fait légitime de ma classe Lecteur qui doit passer mutable.

    Je pense que cet exemple est bien plus parlant pour comprendre mon souci d'origine car, cette fois, ce qui doit passer mutable, c'est une variable essentielle et exposée publiquement par la classe Lecteur.

    Lorsque JolyLoic parle de la sémantique d'une méthode, j'en suis presque amené à penser que les mécanismes du polymorphisme peuvent changer cette sémantique, qu'elle n'est plus la même en fonction du contexte d'où on l'étudie.

    Contexte moteur audio -> méthode Fill n'a qu'un seul but qui ne modifie pas l'objet
    Contexte lecteur audio -> méthode Fill a un autre but modifiant l'objet

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 591
    Points : 30 483
    Points
    30 483
    Par défaut
    En fait, la position dans le flux n'est pas une "propriété intrinsèque" du flux de données audio...
    Les propriété intrinsèques sont:
    • le titre de l'album,
    • la durée de l'album
    • sa taille (éventuellement)
    • les données audio qu'il contient

    La position n'est, effectivement - et bien que tu puisse, d'autre part, demander où le flux audio en est de la lecture - qu'une sorte de cache permettant de retrouver l'échantillon suivant à renvoyer.
    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. #14
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2003
    Messages
    5 272
    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 272
    Points : 10 962
    Points
    10 962
    Par défaut
    La constance est une indication sémantique sur la donnée : savoir si une opération va modifier l'état visible de ton objet. Si dans les détails d'implémentation, il y a des choses qui sont altérées (cache et autres évaluations paresseuses, mutex, ...), ben ... ce sont des détails que l'appelant ne perçoit pas.
    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...

  15. #15
    Expert éminent

    Inscrit en
    novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    La signature de la méthode à implémenter est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Fill( char* data, size_t dataSize ) const.
    Le lecteur attentif aura remarqué le fameux const
    [...]
    Contexte moteur audio -> méthode Fill n'a qu'un seul but qui ne modifie pas l'objet
    Contexte lecteur audio -> méthode Fill a un autre but modifiant l'objet
    Désolé, mais comme deux appels à Fill n'ont pas le même effet -- on ne recoit pas les mêmes données -- , l'erreur pour moi est de mettre Fill comme membre const (à voir les membres de basic_istream, ses concepteurs ont le même avis).

    Un Fill qui pourrait être const aurait une interface comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Fill(size_t pos, unsigned char* data, size_t size) const;
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  16. #16
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut
    Bien vu, j'aurais plutôt tendance à me ranger à cet avis.

    J'ai l'impression que les choses sont plus claires pour moi sur ce sujet maintenant.

    Merci pour vos interventions

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 326
    Points : 41 366
    Points
    41 366
    Par défaut
    C'est justement pourquoi dans le cas des conteneurs, les itérateurs sont des objets séparés, et non inclus dans la liste.
    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.

  18. #18
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : juin 2002
    Messages : 1 309
    Points : 1 033
    Points
    1 033
    Par défaut
    Hum je suis pas sûr d'avoir pigé ta remarque Médinoc

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 326
    Points : 41 366
    Points
    41 366
    Par défaut
    Traduction:
    Quand tu parcoures une liste chaînée, tu ne stockes pas le pointeur "courant" dans la structure liste elle-même, mais tu le gardes à l'extérieur.
    Que ce soit sous la forme d'un itérateur (listes STL) ou autre chose (listes MFC).
    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.

  20. #20
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2003
    Messages
    5 272
    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 272
    Points : 10 962
    Points
    10 962
    Par défaut
    Et aussi pour des histoires de ré-entrance et autres accès concurrents.
    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...

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

Discussions similaires

  1. Réponses: 14
    Dernier message: 21/11/2008, 17h29
  2. Méthodes virtuelle et implémentation
    Par slate dans le forum C++
    Réponses: 2
    Dernier message: 16/02/2006, 18h16
  3. méthodes virtuelles
    Par ep31 dans le forum C++
    Réponses: 2
    Dernier message: 09/11/2005, 18h21
  4. Comment l'appel à une méthode virtuelle....
    Par Blobette dans le forum C++
    Réponses: 7
    Dernier message: 07/12/2004, 14h55
  5. [C#] Méthode virtuelle
    Par jacma dans le forum Windows Forms
    Réponses: 4
    Dernier message: 07/11/2004, 09h18

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