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 :

Variables polyvalentes et surcharge des opérateurs


Sujet :

C++

  1. #1
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut Variables polyvalentes et surcharge des opérateurs
    Bonjour à tous.

    Dans le cadre de mon project CWS (langage interprété), je dois créer une classe de variables supportant les types de variables majeures.

    Pour simplifier la suite de l'écriture du code, j'utilise la surcharge des opérateurs
    Voici à quoi ressemble la structure de la classe:
    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
     
    class cwsVar {
        public:
            friend ostream &operator<<(ostream &, cwsVar &);
     
            cwsVar();
            cwsVar(cwsVar &);
            // should create constructors with different types (int, float, bool & string)
            int getIntVal();
    //        float getFloatVal();
    //        bool getBoolVal();
    //        string getStringVal();
            int getType();
            // on getVal, switch type, and return value formatted to wanted type
     
            // should first make +, -, / and * operators, and then apply it to +=... with *this = value1 + value2
     
            cwsVar &operator=(int);
            cwsVar &operator+(int);
            cwsVar &operator-(int);
            cwsVar &operator*(int);
            cwsVar &operator/(int);
            cwsVar &operator+=(int);
            cwsVar &operator-=(int);
            cwsVar &operator*=(int);
            cwsVar &operator/=(int);
            // also to do for cwsVar, float, bool and string... something easier ?
        private:
            int intVal;
            float floatVal;
            bool boolVal;
            string stringVal;
            int currentType;
    };
    Là où je bloque, c'est que, parti comme ca, je suis bon pour me taper tous les opérateurs pour tous les types (cwsVar, int, float, bool, string).

    N'y a-t-il pas une solution plus simple, avec des templates par exemple ? Pourrait-on imaginer avoir une seulement variable de contenu (remplacant intVal, floatVal etc...) avec un template ainsi que des méthode template ?
    Sachant qu'une fois la classe terminée, je dois pouvoir faire des opérations simple, comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	cwsVar myVar;
    	myVar = 5;
    	cout << myVar.getIntVal() << endl;
    	myVar += 10;
    	cout << myVar.getIntVal() << endl;
    	myVar -= 7;
    	cout << myVar.getIntVal() << endl;
    	myVar /= 2;
    	cout << myVar.getIntVal() << endl;
    	cout << "Size of cwsVar: " << sizeof(myVar) << endl;
    	cout << (myVar + 5) << endl;
    	cwsVar anotherVar = myVar;
    	cout << anotherVar << endl;

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Par défaut
    Regarde du cote de boost::any pour stocker ta valeur. Les operateurs peuvent alors etre definis par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
      template<typename T>
      cwsVar & cwsVar::operator+=(T rhs)
      {
        T nativeValue = boost::any_cast<T>(value_);
        nativeValue += rhs;
        value_ = nativeValue;
      }
    ou value_ est le membre de ta classe de type boost::any

  3. #3
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Merci de ta réponse


    Mais, n'ayant jamais utilisé les templates, j'avoue avoir un peu de mal à comprendre le code. Saurais-tu expliquer ca en bref, ou je ferais mieux de trouver une doc complète sur les templates ? (ce que je fais d'ailleurs à l'instant)

    En réalité, je cherche également à me passer de bibliothèques extérieures (sauf la STL bien sur.)

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Par défaut
    Jette un oeil a la FAQ sur les templates : http://c.developpez.com/faq/cpp/?page=templates.

    Ce que je propose c'est un operator+= qui prend un type T (quelconque) en parametre, et qui va l'ajouter a ta valeur. Lorsque cet operateur est appele, la valeur stockee dans le boost::any est transformee en un objet de type T et l'operateur += du type T est appele.

    Tout marche bien tant que ton type T avec lequel tu appelle cet operateur dispose d'un operateur +=. Si ce n'est pas le cas, tu auras une erreur de compilation disant qu'il n'est pas possible d'instancier la fonction.

    Quant a se passer de bibliotheques exterieures, c'est un noble objectif, mais qui revient dans ce cas precis a reinventer une partie de la roue (ici boost::any, ou quelque chose de similaire). C'est un bon exercice, mais pour un projet serieux c'est surtout une perte de temps, vu que tu vas devoir concevoir, coder, tester et debugger des parties supplementaires.

  5. #5
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Pas besoin enréalité de réinventer la roue.
    J'ai trouvé un système plus simple.

    Par contre, c'est la première fois que je fais de la surcharge et je tombe sur des bugs que je ne m'explique pas...

    Je joins le fichier executable dans un zip pour vous donner la sortie de debug.

    Vous pouvez voir que quand j'additionne var1 et var2, il y a une erreur de calcul que je ne comprends pas. var1 + var2 devrait donner 6, et non un chiffre aberrant.

    Je ne comprends pas pourquoi.

    Voici deux fonctions qui pourraient être en cause, ainsi que la définition de la classe et le main()

    Quelqu'un a une idée de mon erreur ?
    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
    class cwsVar {
        public:
            friend ostream &operator<<(ostream &, const cwsVar &);
     
            cwsVar();
            cwsVar(const cwsVar &);
            cwsVar(int);
            cwsVar(float);
            cwsVar(double);
            cwsVar(bool);
            cwsVar(string);
            cwsVar(const char *);
            int getIntVal();
            float getFloatVal();
            bool getBoolVal();
            string getStringVal();
            int getType();
            cwsVar &operator+(cwsVar &);
            cwsVar &operator-(cwsVar);
            // Encore à implémenter
            /*cwsVar &operator+(cwsVar);
            cwsVar &operator-(cwsVar);
            cwsVar &operator*(cwsVar);
            cwsVar &operator/(cwsVar);
            cwsVar &operator+=(cwsVar);
            cwsVar &operator-=(cwsVar);
            cwsVar &operator*=(cwsVar);
            cwsVar &operator/=(cwsVar);*/
     
            // no : put a creator for each type, but operators only for cwsVar types
            // and then only make operations with cwsVar objects
        private:
            int intVal;
            double floatVal;
            bool boolVal;
            string stringVal;
            int currentType;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    cwsVar &cwsVar::operator+(cwsVar &value) {
        cwsVar result;
        switch(this->currentType) {
            case TYPE_INT: result = this->intVal + value.intVal; break;
            case TYPE_FLOAT: result = this->floatVal + value.floatVal; break;
            case TYPE_BOOL: break; //throw operationNotPermittedError();
            case TYPE_STRING: result = this->stringVal + value.stringVal; break;
        }
        cout << result.getIntVal() << endl;
        return result;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ostream &operator<<(ostream &stream, const cwsVar &var) {
        switch(var.currentType) {
            case TYPE_INT: stream << "TYPE_INT : " << var.intVal; break;
            case TYPE_FLOAT: stream << "TYPE_FLOAT : " << var.floatVal; break;
            case TYPE_BOOL: stream << "TYPE_BOOL : " << var.boolVal; break;
            case TYPE_STRING: stream << "TYPE_STRING : " << var.stringVal; break;
        }
        return stream;
    }
    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
     
    int main(int arc, char **argv) {
    	// fileRenderer renderer = new fileRenderer(argv[1]); // initializes the firts filerenderer with argv[1]
    	// this will be the final step
    	// tests will be made before
        cwsVar var1(4);
        cout << "var1 : " << var1 << endl;
        cwsVar var2("Hello World !");
        cout << "var2 : " << var2 << endl;
        var2 = 2;
        cout << "var2 : " << var2 << endl;
        cwsVar var3(var1 + var2);
        cout << "var1 + var2 : " << (var1 + var2) << endl;
        cout << "var2 + var1 : " << (var2 + var1) << endl;
        cout << "(var1 + var2).getIntVal() : " << (var1 + var2).getIntVal() << endl;
        cout << "var3 : " << var3 << endl;
    	return 0;
    }
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip cws.zip (133,4 Ko, 82 affichages)

  6. #6
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Allelouiha !
    Eurêka.

    à la plac de ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar &operator+(cwsVar &);
    je devais mettre ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar operator+(cwsVar);

  7. #7
    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
    Apparemment ce que tu veux c'est du "type erasure".
    Il y a des trucs en développement pour ça dans boost...

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Citation Envoyé par Antoine_935
    Allelouiha !
    Eurêka.

    à la plac de ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar &operator+(cwsVar &);
    je devais mettre ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar operator+(cwsVar);
    En fait, je dirais plutôt ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar operator+(cwsVar &);
    Et même, si on y ajoute de la const-correctness:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar operator+(cwsVar const &) const;
    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.

  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
    Ou encore, si l'on veut pouvoir bénéficier des conversions implicites pour l'opérande de gauche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cwsVar operator+(cwsVar const &, cwsVar const &)
    {
        // Fonction non membre !
    }

  10. #10
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Cette dernière solution peut également être intéressante dans certains cas.
    Mais dans mon cas, elle n'est pas nécéssaire: la seule chose qu'elle pourrait m'apporter est un code plus lent. (un langage interprété destiné aux applications web a besoin de vitesse, absolument)

    quant à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cwsVar operator+(cwsVar const &) const;
    J'ai essayé, mais cela m'empêche d'accéder à une fonction membre, ce qui me forcerait à faire du copier/coller, qui n'est jamais bon pour les programmes

    Merci à tous pour votre aide.

    Pour ceux que cette variable intéresse, s'il y en a, son code devrait être disponible dans pas trop de temps ici:
    http://sf.net/projects/celsiusws

  11. #11
    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
    Mais dans mon cas, elle n'est pas nécéssaire: la seule chose qu'elle pourrait m'apporter est un code plus lent
    Pas nécessaire OK je veux bien te croire c'est ton projet, mais plus lent certainement pas... C'est complétement équivalent.

    J'ai essayé, mais cela m'empêche d'accéder à une fonction membre, ce qui me forcerait à faire du copier/coller, qui n'est jamais bon pour les programmes
    Si l'opérateur + modifie l'une de ses opérandes, tu as des questions à te poser... Plutôt que de virer les const pour que ça compile, essaye de les mettre partout où c'est nécessaire

  12. #12
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    non, pas ses opérandes, mais il m'empêche étonnamment d'utiliser les fonctions membres, je suis obligé d'accéder directement aux variables, même privées

    Et tu dis que ce ne serait pas plus lent ?
    J'avoue ne pas comprendre comment le compilateur utilisera cette fonction

  13. #13
    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
    non, pas ses opérandes, mais il m'empêche étonnamment d'utiliser les fonctions membres, je suis obligé d'accéder directement aux variables, même privées
    Oui, car tu cherches à appeler une fonction membre non const sur this (l'opérande de gauche de ton appel à operator +). Tes accesseurs de type getXxx() devraient simplement être const, j'imagine qu'ils ne modifient pas les données membres ?

    Et tu dis que ce ne serait pas plus lent ?
    J'avoue ne pas comprendre comment le compilateur utilisera cette fonction
    De la même manière que la version membre. Pour rappel, une fonction membre après compilation ce n'est qu'une fonction libre prenant comme paramètre supplémentaire this.

  14. #14
    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
    non, pas ses opérandes, mais il m'empêche étonnamment d'utiliser les fonctions membres, je suis obligé d'accéder directement aux variables, même privées
    Ce qui signifie que l'interface de ta classe n'est pas const-correcte.

  15. #15
    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
    Pour les templates, je suis en train d'adapter un cours pour developpez, vas voir par là :
    http://www.code-libre.org/alp/templa...templates.html

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

Discussions similaires

  1. polymorphisme et surcharge des opérateurs
    Par j.david dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 02/01/2011, 19h17
  2. surcharge des opérateurs
    Par Arson dans le forum C++
    Réponses: 9
    Dernier message: 30/05/2008, 11h40
  3. Réponses: 2
    Dernier message: 11/01/2008, 10h40
  4. Réponses: 7
    Dernier message: 02/12/2007, 21h43
  5. Surcharge des opérateurs ?
    Par kedare dans le forum Ruby
    Réponses: 3
    Dernier message: 06/11/2006, 23h47

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