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 :

Redéfinition / Surdéfinition d'opérateur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut Redéfinition / Surdéfinition d'opérateur
    Bonjour,

    J'aimerai savoir comment redefinir un opérateur pour une classe donnée.
    Je m'explique, j'ai une classe Element et je voudrais pouvoir l'afficher sur un flot ou le comparer à un autre élément, quel est la syntaxe des déclarations?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Element
    {
      private:
        char* str;
      public:
        void operator<<(ofstream &stream,Element &elt);
        bool operator>(Element &elt);
    };
    Pas de panique je sais que ça ne marche pas, mais pourquoi?

  2. #2
    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
    1/ Ta surcharge de << est incorrecte. Il ne faut pas oublier qu'une surcharge en fonction membre aura toujours comme première opérande l'objet implicite (this). En gros là tu as un opérateur à 3 opérandes.

    Puisque la première opérande doit être un ostream et non un Element, tu es obligé de passer par une fonction non membre. Voir exemples dans la FAQ.

    Autre remarque : il vaut mieux prendre en parmètre une référence constante.

    2/ La déclaration de ton opérateur > est correcte, si ce n'est que là encore il faudrait prendre en paramètre une référence constante.

  3. #3
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut
    D'accord pour l'opérateur <<, mais j'ai vu il me semble (une fois) un truc qui ressemblait à ce que j'ai fait en utilisant le mot-clef friend, comment puis-je faire pour récupérer l'opérateur<< déjà défini dans le langage.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend void operator<<(ofstream &stream,Element &elt);
    ne fonctionne pas.

    D'autre part je ne voit pas paourquoi je dois passer une constante à mon opérateur > et surtout pourquoi je dois passer la variable en référence.

    Merci de ton aide

  4. #4
    Membre chevronné
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Par défaut
    Pour utiliser l'operateur << "standard", il ne faut pas passer par une méthode de la classe, mais par une fonction à coté, qui effectivement aura le prototype:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ofstream & operator<<(ofstream &stream, const Element &elt);
    - Il prend 2 parametres, une référence vers le flux, et une référence vers ton objet
    - Il retourne une reference vers le flux, pour pouvoir chainer les appels, comme avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << "truc " << i << endl;
    - On utilise des références sur le flux puisque l'on veut le modifier (et c'est plus pratique qu'un pointeur, et dans notre cas le flux n'est jamais NULL)
    - On passe une référence sur l'objet pour éviter de le recopier inutilement. Le mot clé "const" permet d'éviter qu'il soit modifié (ce que permet la référence, mais pas la référence constante).

    Donc au final ça resemblera par exemple à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ofstream & operator<<(ofstream &ofs, const Element &elt)
    {
        ofs << "id = " << elt.getId() << ", val = " << elt.getVal();
        //  ou  ofs.write( ... , ... );
     
        return ofs;
    }
    note: vu que ta référence est constante, tu ne peux appeler que des méthodes "const" dessus.

    note 2 : l'utilisation du mot clé friend permet de s'affranchir des méthodes, et d'utiliser directement les variables membres.

    --

    Pour l'operateur >, c'est la même chose, il faut passer une référence constante pour éviter une copie ou une modification. Pour voir si ton Element est superieur à celui passé en paramètre, nul besoin de modifier l'un des deux. La méthode en elle-même devrait être constante aussi, puisqu'elle n'est pas censé modifier l'instance sur laquelle elle est appelée

  5. #5
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut
    D'accord merci beaucoup pour ces explications, un point reste malgré tout en suspend dans ma tête:
    Citation Envoyé par bigquick
    l'utilisation du mot clé friend permet de s'affranchir des méthodes, et d'utiliser directement les variables membres.
    Comment je fais une tel chose, j'ai essayé:
    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
     
    class Element
    {
      private:
        char* str;
      public:
        bool operator>(const Element &elt);
        friend ofstream &operator<<(ofstream &stream,const Element &elt);
        char* getString();
    };
     
    ofstream &operator<<(ofstream &stream,const Element &elt)
    {
      stream<<str;
    }
    Mais ça me marque que str est inconnu.
    Ensuite si j'essaie plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ofstream &Element::operator<<(ofstream &stream,const Element &elt)
    {
      stream<<str;
    }
    Alors il me dit que kla méthode n'est pas une méthode de Element.

  6. #6
    Membre chevronné
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Par défaut
    En effet ce n'est pas une méthode d'Element. C'est bien une fonction à part.
    Donc tu n'as pas accès aux membres magiquement

    Il faut utiliser l'instance d'Element qui est passée en parametre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ofstream&   operator << ( ofstream&  stream,  const Element& elt )
    {
         stream << elt.str;
         return stream;   // <<<< important !
    }
    ps: Loulou24, dans la FAQ il y a l'explication pour faire cohabiter flux et polymorphisme, mais pas d'explication simple sur les flux en général (ou je n'ai pas trouvé ). Est-ce que tu pense que ça serait nécessaire / une bonne idée ?

  7. #7
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut
    Bon tout ça est très clair mais le compilo m'affiche une erreur:

    "liste.cpp" : E2094 'operator<<' non implémenté dans le type 'ofstream' pour les arguments de type 'char *' dans la fonction operator <<(ofstream &,const Element &) en ligne 11

    Là, c'est très étrange je trouve!

  8. #8
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut
    Argh, ok, autant pour moi, c'était ostream et pas ofstream.

    Merci encore de ton aide précieuse

  9. #9
    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
    Tu as inclu <fstream> ?

    Au fait, habituellement on surcharge plutôt pour ostream (classe de base de tous les flux standards de sortie), ainsi tu pourras utiliser celle-ci pour des ofstream, mais aussi pour des ostringstream ou des ostream.

    ps: Loulou24, dans la FAQ il y a l'explication pour faire cohabiter flux et polymorphisme, mais pas d'explication simple sur les flux en général (ou je n'ai pas trouvé ). Est-ce que tu pense que ça serait nécessaire / une bonne idée ?
    Ca depend du genre d'explication que tu voudrais y ajouter.

  10. #10
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Par défaut
    C'est bon, merci à vous deux

  11. #11
    Membre chevronné
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Par défaut
    Simplement un petit post disant qu'on peut surcharger les operateurs << et >> pour écrire ou lire depuis un flux, et que cette méthode permet d'éviter les méthodes maisons ecrireDansFichier(), afficherDansConsole() et j'en passe

    Avec une petite mention précisant que
    Citation Envoyé par Loulou24
    ainsi tu pourras utiliser celle-ci pour des ofstream, mais aussi pour des ostringstream ou des ostream.
    Puis donner un petit exemple expliquant comment ça marche pour un cas simple, avec des notes sur le fait d'utiliser les méthodes constantes ou alors de passer par le mot-clé "friend" (conseillé ? déconseillé ?).

    Et enfin un mot final disant "pour faire cohabiter tout ça avec le polymorphisme, voir le post suivant"

  12. #12
    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
    Ok c'est noté, on va y réflechir.


  13. #13
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    NB:
    "redéfinition" == "overriding" (/ "supplantation") (dans un sous-type, on supplante une fonction par une autre)

    "surcharge" == "overloading" (on rajoute une fonction de même nom qu'une autre existant déjà, mais les signatures sont différentes)

    "surdéfinition" : traduction pour certains de "overloading", d'autres comprennent "overridding". En ce qui me concerne, terme de fait imprécis et à bannir.
    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.

Discussions similaires

  1. Flux & redéfinition de l'opérateur <<
    Par oodini dans le forum Langage
    Réponses: 8
    Dernier message: 02/05/2013, 23h58
  2. Redéfinition de l'opérateur new
    Par Khan34 dans le forum C++
    Réponses: 15
    Dernier message: 05/07/2012, 16h27
  3. Problème redéfinition de l'opérateur []
    Par scary dans le forum Débuter
    Réponses: 2
    Dernier message: 05/03/2010, 11h00
  4. redéfinition de l'opérateur ==
    Par zackrel dans le forum C++
    Réponses: 6
    Dernier message: 24/04/2006, 20h34
  5. POO + surdéfinition d'opérateur - Visual Studio
    Par mike109g dans le forum Visual C++
    Réponses: 2
    Dernier message: 13/11/2004, 16h27

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