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

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

 C++ Discussion :

le mot clef "static"


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Janvier 2009
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 17
    Points : 11
    Points
    11
    Par défaut le mot clef "static"
    Bonjour,

    Je ne comprends pas toujours l'utilisation du mot clef "static" en c++, j'ai l'impression qu'il y a plusieurs cas bien differents :

    - static fonction() dans un .cpp : la fonction est locale au fichier
    - static fonction() dans un .h : fonction de classe, appelee sans instance d'objet

    - static variable dans un .cpp : variable de classe, commune a toutes les instances
    - static variable dans un .h : idem

    est-ce bien ca ? si oui, quel est l'interet d'utiliser le meme mot clef pour deux choses bien differentes ? (je pense aux deux premiers cas)

    Merci

  2. #2
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    C++ / Le mot clé STATIC



    Syntaxe

    static <définition données> ;

    static <nom d'une fonction> <définition de la fonction> ;

    Description

    Le spécificateur de classe de stockage static, utilisé avec une variable locale, permet de préserver la dernière valeur entre les appels successifs à cette fonction.
    Une variable statique agit comme une variable locale mais a une durée de vie d'une variable externe.
    Dans une classe, les données et fonctions membre peuvent être déclarées statiques.
    Une seule copie de la donnée statique existe pour tous les objets de la classe.
    Une fonction membre statique d'une classe globale a un lien externe.
    Un membre d'une classe locale n'a pas de lien.
    Une fonction membre statique est associée uniquement à la classe dans laquelle elle a été déclarée.
    Par conséquent, de telles fonctions membre ne peuvent pas être virtuelles.
    Les fonctions membre statiques ne peuvent appeler que d'autres fonctions membre statiques et n'ont accès qu'aux données statiques.
    De telles fonctions membre n'ont pas de pointeur this.

    Exemple

    static int iCompteur;
    static void <nom d'une fonction> (void) {<instructions>};

  3. #3
    Membre à l'essai
    Inscrit en
    Janvier 2009
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Salut, en fait j'aurais peut etre du precise que je m'etais renseigne avant de poser la question, mais que malgre tout le doute subsiste (c'est pourquoi je la pose sur un forum avec "mes mots")

    en fait j'ai l'impression que la seule difference entre la declaration dans un .cpp ou un .h est l'acces a la variable/fonction statique (.h -> accessible de l'exterieur, .cpp -> juste dans le fichier), mais que derriere le principe (rendre une variable ou une fonction independante des instances d'une classe) est le meme

    j'ai bon ?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2009
    Messages : 110
    Points : 85
    Points
    85
    Par défaut
    la réponse est dans cette phrase
    Une variable statique agit comme une variable locale mais a une durée de vie d'une variable externe.
    si tu déclare ta variable dans ton .cpp, la variable sera locale et donc elle aura une durée de vie limitée, par contre si tu déclare ta variable autant que variable static dans ton .h, elle aura une durée de vie d'une variable externe, c'est à dire elle ne sera détruite qu'à la fin de l'exécution de ton programme.

    J'espère que ça réponds à ta question.

  5. #5
    Membre à l'essai
    Inscrit en
    Janvier 2009
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Oui je pense que c'est a peu pres clair...

    merci !

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 380
    Points : 41 576
    Points
    41 576
    Par défaut
    Ma version de l'explication:
    • fonction libre/variable globale static: Limite la portée de la fonction libre ou variable globale au fichier source (au lieu de tout le projet).
    • variable locale static: La variable locale se comporte comme une variable globale (durée de vie, multithreading), bien que sa portée soit toujours limitée à celle de la fonction.
    • fonction membre static: La fonction se comporte comme une fonction libre: pas de this, la fonction n'est pas appelée sur un objet. Mais elle peut toujours accéder aux membres privés de sa classe et est toujours sujette aux restrictions d'accès de la classe.
    • variable membre static: Se comporte comme une variable globale, mais est toujours sujette aux restrictions d'accès de la classe.

  7. #7
    Membre à l'essai
    Inscrit en
    Janvier 2009
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Merci ! c'est bien ce que j'avais compris... mon doute vient du fait que le meme mot clef ("static" donc) a une incidence et des effets differents suivant l'endroit ou il est utilise (fonction libre, fonction membre...). A la place de monsieur Stroustrup, j'aurai simplement mis deux mots clefs differents

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Kyle128 Voir le message
    Salut, en fait j'aurais peut etre du precise que je m'etais renseigne avant de poser la question, mais que malgre tout le doute subsiste (c'est pourquoi je la pose sur un forum avec "mes mots")

    en fait j'ai l'impression que la seule difference entre la declaration dans un .cpp ou un .h est l'acces a la variable/fonction statique (.h -> accessible de l'exterieur, .cpp -> juste dans le fichier), mais que derriere le principe (rendre une variable ou une fonction independante des instances d'une classe) est le meme

    j'ai bon ?
    Salut,
    La problématique autour du static concerne 2 éléments plus ou moins liés : la durée de vie d'une variable ('storage duration') et le lien ('linkage) d'une unité de compilation (translation unit) et n'a rien à voir avec le .h ou le .cpp (ou presque).
    Regardons d'abord les variables.
    Supposons le fichier d'en-tête suivant :
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef A_H_INCLUDED
    #define A_H_INCLUDED
     
    int a;
    static int b;
    extern int c;
     
    #endif // A_H_INCLUDED
    Puis considérons les deux fichiers sources suivants :
    a.cpp
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "a.h"
    int main()
    {
       return 0;
    }
    Tu compiles ce projet et... première erreur au link :
    multiple definition of `a'
    Bon. Mettons cette déclaration en commentaire et essayons maintenant avec les fichiers suivants :
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef A_H_INCLUDED
    #define A_H_INCLUDED
     
    // int a;
    static int b;
    extern int c;
     
    void fonction();
     
    #endif // A_H_INCLUDED
    a.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "a.h"
    #include <iostream>
    void fonction()
    {
       std::cout<<"b dans fonction : "<<b<<std::endl;
       b++;
       std::cout<<"b dans fonction apres increment: "<<b<<std::endl;
    }
    et main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "a.h"
    #include <iostream>
     
    int main()
    {
       std::cout<<"b dans main : "<<b<<std::endl;
       fonction();
       std::cout<<"b dans main apres fonction: "<<b<<std::endl;
       return 0;
    }
    Ca compile, on exécute et ... première surprise :
    b dans main : 0
    b dans fonction : 0
    b dans fonction apres increment: 1
    b dans main apres fonction: 0
    De nouveau, modifions légèrement notre programme pour nous intéresser maintenant à la variable 'c' :
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef A_H_INCLUDED
    #define A_H_INCLUDED
     
    //int a;
    static int b;
    extern int c;
     
    void fonction();
     
    #endif // A_H_INCLUDED
    a.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "a.h"
    #include <iostream>
    void fonction()
    {
       std::cout<<"c dans fonction : "<<c<<std::endl;
       c++;
       std::cout<<"c dans fonction apres increment: "<<c<<std::endl;
    }
    main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "a.h"
    #include <iostream>
    
    int main()
    {
       std::cout<<"c dans main : "<<c<<std::endl;
       fonction();
       std::cout<<"c dans main apres fonction: "<<c<<std::endl;
       return 0;
    }
    La compilation échoue avec des erreurs du type :
    undefined reference to `c'
    Modifions légèrement notre a.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "a.h"
    #include <iostream>
    
    int c;
    
    void fonction()
    {
       std::cout<<"c dans fonction : "<<c<<std::endl;
       c++;
       std::cout<<"c dans fonction apres increment: "<<c<<std::endl;
    }
    La compilation réussie et on obtient à l'exécution :
    c dans main : 0
    c dans fonction : 0
    c dans fonction apres increment: 1
    c dans main apres fonction: 1
    Quelques explications s'imposent

    Derrière ces trois lignes de code (int a; static int b; et extern int c; ), se cache trois choses différentes :
    int a; : on définit une variable qui sera visible sur toutes les unités de translation. Donc, a est défini dans a.cpp et dans main.cpp d'où le conflit à l'édition de lien.

    static int b; : on définit une variable mais celle-ci reste lié à l'unité de compilation qui la contient. Donc a dans main.cpp et a dans a.cpp désignent 2 variables différentes. D'où, 1/ pas d'erreur de link et 2/ modifier dans une unité (par expl, a.cpp) n'a pas d'effet sur l'autre (main.cpp) car ce sont 2 variables complètement différentes.

    extern int c; : on déclare une variable. Toutes les unités rencontrant cette ligne ont connaissance de l'existence de cette variable, mais personne ne la définit -> d'où notre erreur de link. En ajoutant int c; dans a.cpp, on définit cette variable. Donc l'utilisation de 'a' dans a.cpp et dans main.cpp réfère à la même variable définie dans a.cpp. -> D'où les modifs apportées dans l'une sont visibles dans l'autre.

    La durée de vie d'une variable dans un bloc (une fonction, par exemple) : cette variable est construite au moment de sa définition dans un bloc et détruite à la sortie du bloc qui la définie. Partons d'un exemple :
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include <iostream>
    #include <string>
     
    struct A
    {
       A(std::string nom_):m_nom(nom_)
       {
          std::cout<<"creation de "<<m_nom<<std::endl;
       }
       ~A()
       {
          std::cout<<"destruction de "<<m_nom<<std::endl;
       }
     
       std::string m_nom;
    };
     
    A a("a");
     
    void fonction()
    {
       std::cout<<"Debut de fonction"<<std::endl;
       A b("b");
       std::cout<<"b existe !"<<std::endl;
       {
          std::cout<<"un nouveau bloc"<<std::endl;
          A c("c");
          std::cout<<"c existe !"<<std::endl;
       }
       std::cout<<"On est sorti du bloc"<<std::endl;
    }
     
    int main()
    {
       std::cout<<"Entree dans main"<<std::endl;
       std::cout<<"Avant fonction"<<std::endl;
       fonction();
       std::cout<<"Apres fonction !"<<std::endl;
       std::cout<<"Bye..."<<std::endl;
     
       return 0;
    }
    La sortie est :
    creation de a
    Entree dans main
    Avant fonction
    Debut de fonction
    creation de b
    b existe !
    un nouveau bloc
    creation de c
    c existe !
    destruction de c
    On est sorti du bloc
    destruction de b
    Apres fonction !
    Bye...
    destruction de a
    'a' est créé à l'initialisation du programme et détruite à la sortie du programme ;
    'b' est après sa définition dans la fonction et détruite à la sortie de fonction ;
    'c' est crée après sa définition dans le bloc et détruite en sortie du bloc.

    static permet d'étendre la durée de vie d'une variable définit dans un bloc au delà de la durée de vie du bloc sur toute la durée du programme. Elle n'est construite qu'une fois, la première fois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #include <iostream>
    #include <string>
     
    struct A
    {
       A(std::string nom_):m_nom(nom_)
       {
          std::cout<<"creation de "<<m_nom<<std::endl;
       }
       ~A()
       {
          std::cout<<"destruction de "<<m_nom<<std::endl;
       }
     
       std::string m_nom;
    };
     
    A a("a");
     
    void fonction()
    {
       std::cout<<"Debut de fonction"<<std::endl;
       // notre static :
       static A d("d");
    }
     
    int main()
    {
       std::cout<<"Entree dans main"<<std::endl;
       std::cout<<"Avant fonction"<<std::endl;
       fonction();
       std::cout<<"Apres fonction !"<<std::endl;
       std::cout<<"Avant 2nd appel de fonction"<<std::endl;
       fonction();
       std::cout<<"Apres 2nd appel de fonction !"<<std::endl;
     
       std::cout<<"Bye..."<<std::endl;
     
       return 0;
    }
    Résultat :
    creation de a
    Entree dans main
    Avant fonction
    Debut de fonction
    creation de d
    Apres fonction !
    Avant 2nd appel de fonction
    Debut de fonction
    Apres 2nd appel de fonction !
    Bye...
    destruction de d
    destruction de a
    On voit que d n'est créé qu'une fois : la première fois qu'on arrive à son niveau dans fonction et détruite à la fin du programme. Note que d aurait très bien pu être détruite après a

    Dernier point sur les variables, les variables d'une classe : c'est un peu le même principe que précédemment.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class A
    {
       int m1;
       static int m2;
    };
    m1 a une durée de vie égale à celle de l'objet qui la contient. Par exemple, dès que tu définis un objet A a; la variable m1 est définie et sera détruite en même temps que a. Si tu définis 2 objets : A a1 et A a2 alors deux variables m1 sont créés, une pour chacun des objets. a1.m1 permet d'accéder à la variable de l'objet a1 et a2.m1 à celle de a2.
    m2 a une durée de vie égale à celle du programme. Un peu comme les variables globales déclarées avec extern. D'ailleurs, m2 nécessite d'être définit car la déclaration dans la classe ne suffit pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <iostream>
    struct A
    {
    static int m2;
    };
    int main()
    {
       std::cout<<A::m2<<std::endl;
       return 0;
    }
    Donne une erreur au link !
    Il faut la définir une seule fois, en général dans a.cpp, mais pour l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <iostream>
    struct A
    {
    static int m2;
    };
    int A::m2 = 0;
    int main()
    {
       std::cout<<A::m2<<std::endl;
       return 0;
    }

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Pour les fonctions, c'est toujours le même principe :
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef A_H_INCLUDED
    #define A_H_INCLUDED
     
    void fonction();
    extern void fonction2();
    static void fonction3();
     
    #endif // A_H_INCLUDED
    a.cpp:
    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
    #include "a.h"
    #include <iostream>
     
    void fonction()
    {
       std::cout<<"fonction dans a.cpp"<<std::endl;
       fonction3();
    }
     
    void fonction2()
    {
       std::cout<<"fonction2 dans a.cpp"<<std::endl;
    }
     
    void fonction3()
    {
       std::cout<<"fonction3 dans a.cpp"<<std::endl;
    }
    main.cpp :
    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
    #include "a.h"
    #include <iostream>
     
     
    void fonction3()
    {
       std::cout<<"fonction3 dans main.cpp"<<std::endl;
    }
     
    int main()
    {
       fonction();
       fonction2();
       fonction3();
       return 0;
    }
    Donne comme résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    fonction dans a.cpp
    fonction3 dans a.cpp
    fonction2 dans a.cpp
    fonction3 dans main.cpp
    Note que si on enlève l'include du main.cpp pour le définir ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
     
    extern void fonction();
    extern void fonction2();
    extern void fonction3();
     
    int main()
    {
       fonction();
       fonction2();
       fonction3();
       return 0;
    }
    On a une erreur au link : undefined reference to `fonction3()'.
    Car la 'portée' d'une fonction définit comme static ne s'étend pas au delà de l'unité de translation dans laquelle elle est définie.

    Un point différent pour les fonctions est le spécifieur 'inline' qui entre autre permet à une définition de fonction d'être inclue dans plusieurs unité de compilation, à charge au compilateur de faire le ménage :
    a.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef A_H_INCLUDED
    #define A_H_INCLUDED
     
    inline void fonction()
    {}
     
    #endif // A_H_INCLUDED
    a.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #include "a.h"
     
    void fonction2()
    {
       fonction();
    }
    et main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "a.h"
     
    int main()
    {
       fonction();
       return 0;
    }
    Ceci ne provoque pas d'erreur au link : une seule définition de fonction est prise en compte.

    Pour les fonctions des classes, c'est un peu comme pour les variables de classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct A
    {
       void fonction();
       void fonction2()
      {
      }
      static void fonction3();
      inline void fonction4();
    };
    fonction n'est accessible qu'avec des objets A et doit être définie une seule fois. Sinon, tu as une erreur au link.
    fonction2 n'est accessible qu'avec des objets A et doit être définie une seule
    fois. Sinon tu as une erreur à la compilation
    fonction3 est accessible sans objets A et doit être définie une seule fois. Sinon, tu as une erreur au link.
    fonction4 est accessible avec un objet A et doit être définie une seule fois. Sinon... tu n'as aucune erreur ni au link ni à la compilation ce que pour l'instant je ne m'explique pas trop...

  10. #10
    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 : 50
    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 Kyle128 Voir le message
    A la place de monsieur Stroustrup, j'aurai simplement mis deux mots clefs differents
    Avoir trop de mots clefs différents pose aussi problème (par exemple de compatibilité avec du code écrit avant l'introduction des nouveaux mots clefs).

    Par contre, en effet, "static" est un mot clef sur lequel à peu près tout le monde s'accorde à dire qu'il a été trop surchargé. Mais c'est un peut tard pour corriger ça.

  11. #11
    Membre à l'essai
    Inscrit en
    Janvier 2009
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Par contre, en effet, "static" est un mot clef sur lequel à peu près tout le monde s'accorde à dire qu'il a été trop surchargé. Mais c'est un peut tard pour corriger ça.
    Ok, parfait, ca montre que j'ai compris

    3DArchi : merci pour ta longue explication, je lirai ca ce soir bien au chaud

Discussions similaires

  1. Utilisation du mot-clef "static"
    Par sir_gcc dans le forum Langage
    Réponses: 3
    Dernier message: 16/04/2007, 11h18
  2. mot-clef static
    Par keil dans le forum C++
    Réponses: 8
    Dernier message: 25/01/2006, 17h11

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