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 :

opérateurs surchargés conversion de type


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2007
    Messages : 11
    Points : 5
    Points
    5
    Par défaut opérateurs surchargés conversion de type
    Bonjour à tous.
    Je rencontre un petit soucis sur la surcharge d'opérateur.
    C'est un domaine de programmation que j'utilise depuis peu.
    Voici un extrait de code :

    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
    // .h
    class TimeStampOBJ{
      public :
        TimeStampOBJ();  
        TimeOBJ &getTimeFromLastCheck();
        TimeOBJ &getTimeFromBeginning();
    	TimeOBJ operator=( TimeStampOBJ &obj );
      private :
        TimeOBJ now=0;
        void compute();
    }
    // .cpp
    TimeOBJ TimeStampOBJ::operator=( TimeStampOBJ &obj ){
      compute();
      return( now );
    }
    // Projet
    TimeStampOBJ objTimeStamp = TimeStampOBJ();
    TimeOBJ objNow = objTimeStamp;
    Pour avoir le code complet :
    www.github.com/YannChansigaud/TimeStampOBJ
    www.github.com/YannChansigaud/TimeOBJ

    TimeStampOBJ permet de stocker la valeur de temps au delà de uint32_t en microsecondes en utilisant des objets de type TimeOBJ. Fonctionne très bien.

    Cependant, je souhaiterais implémenter l'opérateur =
    Afin de remplacer l'appel de la méthode get() qui renvoie un objet TimeOBJ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TimeOBJ now_value = objTimeStampOBJ.get()
    Deviendrait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TimeOBJ now_value = objTimeStampOBJ;
    J'ai l'erreur :
    Operande are TimeOBJ and TimeStampOBJ
    J'ai justement suivi des tutos, cours et guidance sur internet pour implémenter ses opérateurs surchargés et, du reste, [ ], =, +=, -=, ==, /=, ++, --, <, >, <=, >= sont implémentés et fonctionnels dans la classe TimeOBJ.
    Cependant, je ne récupère qu'une valeur à zéro sur l'opérateur = dans la classe TimeStampOBJ. Je sais que je suis passé à côté de quelque chose mais j'ai trop la tête dedans et je vois plus rien...

    De plus, je n'ai pas trop saisie comment faire la différence entre un l'opérateur permettant :
    et
    (Qui est l_value et qui est r_value)

    Aussi, dans l'opérateur += ou -= je ne comprends pas pourquoi certain tutos indiquent que la méthode doit renvoyer l'objet alors que la méthodes s'applique sur les variables privée même de l'instanciation et, de plus, mes méthodes en void fonctionnent.

    PS: je suis sur mon téléphone (c'est pas évident)

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 053
    Points
    33 053
    Billets dans le blog
    4
    Par défaut
    Pour avoir une syntaxe comme TimeOBJ now_value = objTimeStampOBJ il faut un opérateur défini comme TimeOBJ& operator=(const TimeStampOBJ&);. Tu peux aussi fournir un constructeur qui permet la conversion.
    Pour les syntaxes j'utilise généralement cette source.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2007
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Merci pour la source, je la garde dans mes marques pages

    Je crois que le soucis vient de ceci :

    Dans TimeStampOBJ j'ai des opérateurs de comparaison de TimeOBJ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public :
       bool TimeStampOBJ::operator>( const TimeOBJ &TimeToCompare );  // Me permet de faire if( TimeStampOBJobj > TimeOBJ val){...}
      TimeOBJ &TimeOBJ::get(){  return( now ); }  // Même que now soit en privé, ça fonctionne.
    private :
       TimeOBJ now=0;
    Dans TimeOBJ j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    
    public :
       void TimeOBJ::operator=(  const TimeOBJ &TimeToSetTo    );  // Me permet d'affecter la valeur d'un TimeOBJ à un autre TimeOBJ


    Et il me faudrait avoir dans TimeOBJ
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TimeOBJ &TimeOBJ::operator=(  const TimeStampOBJ&TimeToGetBack    );  // pour affecter la valeur stocker dans TimeStampOBJTimeToGetBack    à un objet TimeOBJ
    
    Donc TimeStampOBJ a besoin de TimeOBJ
    et TimeOBJ aurait besoin de TimeStampOBJ

    Comment fait-on des liaisons croisées entre les classes ?

    Pour rappel, TimeStampOBJ permet de comparer des éléments TimeOBJ et contient 2 objets privés de type TimeOBJ

    Il y a-t-il une solution pour, dans TimeStampOBJ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    
    TimeOBJ &TimeStampOBJ::operator=( const TimeStampOBJ &TimeToGetBack ){ return ( TimeToGetBack.get() ) };   // le compilateur ne cherche des methodes candidats QUE dans la classe TimeOBJ

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 580
    Points : 7 712
    Points
    7 712
    Par défaut
    Bonjour,

    - une l-value est une entité qui peut stocker une valeur. Dans expression d'affectation, elle seule peut être à gauche du égal (d'où le l- comme left).
    - une r-value (avec r- comme right) est une valeur. Elles ne sont jamais à gauche d'un égal.
    Dans l'expression a = 2;, a est une l-value et 2 est une r-value.
    Dans l'expression t[a] = b;, t[a] est une l-value et a et b sont utilisées en r-value (on ne s’intéresse qu'au contenu des ces dernières).

    Si TimeStampOBJ contient des TimeOBJ alors forcément c'est TimeStampOBJ qui dépend de TimeOBJ. D'où TimeStampOBJ.h doit inclure TimeOBJ.h et surtout pas l'inverse. Le définition de TimeOBJ ne devrait aucunement dépendre du type TimeStampOBJ.
    D'où dans la définition de TimeOBJ :
    - on ne peut pas déclarer TimeOBJ& operator=( const TimeStampOBJ& );. Mais on a la solution indiquée par Bousk à placer dans class TimeStampOBJ.
    - on n'a normalement pas besoin de définir void TimeOBJ::operator=( const TimeOBJ& ); car le compilateur sait la définir automatiquement et qu'en plus il utilisera le bon type de retour au lieu de void.

    Ta définition TimeOBJ &TimeStampOBJ::operator=( const TimeStampOBJ &TimeToGetBack ) n'a pas vraiment de logique elle correspond à une affectation entre 2 TimeStampOBJ qui retournerait quelque chose d'autre!

    Et pour revenir à ton problème initial, vouloir une conversion implicite entre TimeStampOBJ et TimeOBJ est une très mauvaise idée. Il risque d'y avoir de fâcheuses conséquences car un TimeOBJ n'est absolument pas un TimeStampOBJ. La fonction get() est très bien.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2007
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Merci pour toutes ses informations, j'avais clairement besoin d'une piqure de rappel.
    C'est la 1ère fois que je me développe une classe aussi "poussée" et c'est la 1ère fois que j'utilise la surcharge d'opérateur.
    Je me rappelle l'avoir vu en cours mais mon BTS a déjà 10 ans (c'est loin) et je me souviens que je n'avais pas spécialement bien cerné le fonctionnement.

    Par contre quand tu dis :
    - on n'a normalement pas besoin de définir void TimeOBJ::operator=( const TimeOBJ& ); car le compilateur sait la définir automatiquement et qu'en plus il utilisera le bon type de retour au lieu de void.
    Quand on instancie une classe, on obtient une adresse mémoire pointant sur la localisation de l'instanciation de la classe non ?
    si on fait :
    class obj = autreOBJdeMemeClass : c'est le compilateur qui en principe sait quoi faire
    mais si on a
    class obj = class();
    obj = autreOBJdeMemeClass : c'est une copie intégrale de la 2nd instanciation sur la 1ère (c'est bien ça ? )

    du coup, surcharger l'opérateur = n'a d'utilité que si on veut conserver certain attribues de la 1ère instanciation inchangée (j'ai juste ? )

    J'ai simplifié et clarifié mon compte avec getTimeFromLastCheck() et getTimeFromBeginning();

    Par contre, je viens de me souvenir que des liaisons croisées entre classe n'est possible qu'avec le type T classe... mais je crois que je vais rester sur du simple
    edit : en faite non, c'est pour avoir une fonction qui suit des opérations différentes suivant le type passé en paramètre (si j'ai bien compris...)

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2007
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // attention c'est un mixe entre .h et .cpp pour une meilleur lisibilité
    class TimeStampOBJ :
      public :
        TimeOBJ TimeStampOBJ::get(){  return( now  );  } 
        TimeOBJ TimeStampOBJ::operator=( const TimeOBJ &TimeToCompare ){   return( now  );  } 
    
      private :
    
        TimeOBJ now;
    En faite, ce que je ne comprends pas :
    c'est que :
    TimeOBJ objTime = TimeOBJ();
    TimeStampOBJ
    objTimeStamp = TimeStampOBJ();

    objTime = objTimeStamp.get(); // ça, ça fonctionne mais je comprends très bien pourquoi car j'appelle la méthode get() pas d’ambiguïté
    mais
    objTime = objTimeStamp; // même si c'est pas vraiment conseillé pour la compréhension

    pourquoi le compilateur chercher une méthode candidate dans la classe TimeOBJ et pas dans la classe TimeStampOBJ (alors qu'il y a une méthode disponible pour) ?

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 053
    Points
    33 053
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Hitsugaya81 Voir le message
    pourquoi le compilateur chercher une méthode candidate dans la classe TimeOBJ et pas dans la classe TimeStampOBJ (alors qu'il y a une méthode disponible pour) ?
    Parce qu'un compilateur c'est con. Il a ses règles et c'est à toi de les suivre. Il ne fera que suivre les règles qui ont été établies.

    objTime = objTimeStamp; est un sucre syntaxique bien pratique mais l'appel réel est objTime.operator=(objTimeStamp); alors si une telle fonction n'existe pas, même si une autre ferait l'affaire, il sait pas faire.
    À la limite avec un opérateur de conversion, il peut faire une conversion implicite et utiliser l'assignation. Mais as-tu un tel opérateur ? non

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2007
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Merci pour toutes les infos.

    Haaaaa.... Les bases les bases... Si on ne pouvait jamais les oublier (le monde partirait pas en couille)

    Merci en tout cas.
    Bonne soirée

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conversion de type
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 06/07/2004, 10h30
  2. [MYSQL] conversion de type sur import de script
    Par sebos63 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/08/2003, 10h00
  3. opérateur non applicable à ce type d'opérande
    Par Amon dans le forum Langage
    Réponses: 3
    Dernier message: 11/06/2003, 18h07
  4. Réponses: 2
    Dernier message: 05/06/2002, 12h29

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