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 :

surcharge de fonction.


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut surcharge de fonction.
    Bonjour.

    J'ai le code suivant (qui est une version simplifié d'une gestion de variant que j'essaye de mettre en place).

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    using namespace std;
    #include <stdio.h>
     
    class ebovar
    {
    public:
    	void *pvalue;
     
    	ebovar()
    	{
    		pvalue = (void*)new int(0);
    	}
     
    // integer function
    	ebovar(int v)
    	{
    		pvalue = (void*)new int(v);
    	}
    	operator int()
    	{
    		return *(int *)pvalue;
    	}
    };
     
    ebovar operator+(ebovar left_op, ebovar right_op)
    {
    	return (ebovar)((int)left_op + (int)right_op);
    }
     
    ebovar Addition(ebovar a, ebovar b)
    {
    	return a + b;
    } 
     
    int main(int _argc, char **_argv);
     
    int main(int _argc, char **_argv)
    {
    	ebovar _x = (ebovar)10;
    	ebovar _y = (ebovar)12;
    	ebovar _result = Addition(_x, _y);
     
    	int _z = 32;
    	ebovar _result2 = Addition(_x, _z);
     
    	_z = Addition(_y, _z);
     
    	printf("%d\n", *(int *)_result.pvalue);
    	printf("%d\n", *(int *)_result2.pvalue);
    	printf("%d\n", _z);
    }
    J'arrive pas a comprendre pourquoi Addition(_x, _z); ne génère pas d'erreur alors qu'il n'y a pas de fonction définie pour prendre en charge une (ebovar + int).
    Le plus étrange c'est que tout cela fonctionne exactement comme je le souhaite et m'affiche bien
    22
    42
    44

    Que se passe t-il ?

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Il se passe que tu as un opérateur de conversion implicite (operator int()) et surtout un constructeur implicite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class ebovar {
    public:
        ebovar();
        ebovar(int v);
    };
    Pour trouver quelle fonction appeler, le compilateur cherche d'abord parmi les signatures exactes ou approchées (const&, etc...) puis cherche avec des conversions implicites (et termine sur une fonction utilisant ..., s'il y en a).

    En fait, c'est un peu ce qu'il se passe quand tu fais 1+2.0. Il n'y a pas de "fonction" + pour int et double. par contre, il y a une conversion implicite de int vers double, et un +(double, double).
    En fait, il n'y a pas de fonctions, mais le langage utilise le même mécanisme.

    Tout constructeur prenant un argument sert pour la conversion du type de l'argument vers le type de la classe.
    S'il n'est pas spécifié comme explicit, cette conversion est possible dans le cadre des conversions implicites.

    Du coup, pour Addition(ebovar(4), 17), le compilateur effectue Addition(ebovar(4), ebovar(17)).

    Si tu ne veux pas que cette conversion ait lieu, il faut définir ton constructeur comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class ebovar {
    public:
        ebovar();
        explicit ebovar(int v);
    };
    PS: pourquoi définir addition. Tu peux écrire directement _x+_z, voire operator+(_x, _z).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Salut et merci.

    Tout d’abord pour la fonction Addition c'est juste parce que je fais quelques essais

    Sinon j'ai bien compris que dans le cas de l'appel a la fonction Addition mon int est casté en ebovar.

    Si je fais directement _z = _y + _z
    Cela ne fonctionne pas car le compilateur me dit qu'il ne sait pas quel opérateur choisir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    error: ambiguous overload for 'operator+' in '_a + _b'
    note: candidates are: operator+(int, int) <built-in>
    note:                 ebovar operator+(ebovar, ebovar)
    PS: ça n'a rien a voir, mais comment tu as fait pour colorer "Addition(ebovar(4), 17)" dans ton message ?

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Justement, c'est à cause des surcharges qu'il ne sait pas quoi faire:
    pour ton int + eboval, il te dit qu'il a le choix entre:
    • convertir l'eboval implicitement en int, et utiliser int + int.
    • convertir l'int implicitement en eboval, et utiliser eboval + eboval.

    Les deux lui coutant le même prix logique (une conversion implicite), il ne sait pas quoi choisir.
    La solution, c'est de rendre l'une des deux conversions explicit.

    A toi de voir si tu veux convertir en int ou en eboval. Personnellement, dans ton cas, je convertirai plutot en int, pour ne pas créer inutilement un pointeur.


    Et pour la coloration, il y a une astuce, il faut utiliser la balise [codeinline] ou la version courte: [c].
    Il faut qu'il y ait un caractère non blanc après pour que le saut de ligne soit pris en compte derrière (un point par exemple)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Bon.

    Je n'ai pas réussi a rendre l'une des deux conversions explicite.
    Ce n'est pas grave. J'ai surchargé l'opérateur + avec les deux fonctions suivantes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ebovar operator+(ebovar left_op, int right_op)
    {
    	return (ebovar)((int)left_op + right_op);
    }
     
    ebovar operator+(int left_op, ebovar right_op)
    {
    	return (ebovar)(left_op + (int)right_op);
    }
    Par contre j'aurai bien voulu savoir s'il était possible
    de surcharger l'opérateur en fonction du type retourné.

    J'aurai bien voulu que ebovar _result = _ebovalue + _intvalue; utilise la surcharge précédente.
    Par contre int _result = _ebovalue + _intvalue; n'a pas besoin de passer par un CAST en ebovar avant de revenir en int.

    Comment faire?
    Le compilateur n'a pas l'air de vouloir me laisser faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int operator+(ebovar left_op, int right_op)
    {
    	return (int)left_op + right_op;
    }
    car évidement il me dit que le surcharge est déja définie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    test.cpp:52: error: new declaration 'int operator+(ebovar, int)'
    test.cpp:40: error: ambiguates old declaration 'ebovar operator+(ebovar, int)'

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    C'est a cause de tes conversions que tu as ce problème.

    Essaie ceci:
    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
    class ebovar {
        int value;
    public:
        explicit ebovar(int i = 0) : value(i) {}
        operator int() const {return value;}
    };
     
    //C'est magique, comme la conversion vers int est implicite, je n'ai pas de surcharge requise
     
    int main() {
        ebovar a = 1;
        ebovar b = 2;
        ebovar somme = a+b, produit(a*b);
        ebovar d;
        d = ebovar(a*b);
        return (1+somme) + d*2;
    }
    PS: normalement, ca doit compiler.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Oula.

    Bon alors ça compile pas.
    Mais en plus ça se complique

    Visiblement le explicit génère le message d'erreur suivant
    error: conversion from 'int' to non-scalar type 'ebovar' requestedSi j'enlève le explicit, ça semble fonctionner.

    Mais losrque j'ajoute le type float au variant (puisque c'est le but)
    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
    class ebovar {
        int value;
        float fvalue;
    public:
        ebovar(int i = 0) : value(i) {}
        operator int() const { return value; }
     
        ebovar(float i = 0) : fvalue(i) {}
        operator float() const { return fvalue; }
    };
     
    int main() {
    	ebovar _a = 8;
    	int _b = 5;
    	ebovar _c = 5.1f;
    	int _d = _a + _b + _c;
    	printf("%d\n", _d);
    }
    J'obtient toujours le même problème de surcharge.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    leternel.cpp:21: error: ambiguous overload for 'operator+' in '_a + _b'
    leternel.cpp:21: note: candidates are: operator+(int, int) <built-in>
    leternel.cpp:21: note:                 operator+(float, int) <built-in>

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Alors tu vas devoir prendre l'autre chemin.

    Ma première proposition, c'est de sortir des ebovar le plus tot possible.
    Visiblement, ton besoin, c'est de rester entre ebovar aussi longtemps que possible.

    Donc, supprime tes opérateurs de conversion vers int ou float.
    Ou au moins rends les explicites.

    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
    43
    44
    class ebovar {
    private:
        enum {type_int, type_float} type;
        union {
            int i;
            float f;
        };//union interne anonyme, les champs sont directement accessible
    public:
        ebovar() {}
        ebovar(ebovar const& other);//a toi de voir.
     
        ebovar(int i) : i(i) {}
        ebovar(float f) : f(f) {}
     
        explicit operator int() const { /*controle d'erreur;*/ return i; }
        explicit operator float() const { /*controle d'erreur;*/ return f; }
     
        ebovar&& operator+=(ebovar const& other) {
            //ici, tu change la valeur de cette variable
            return *this;
        }
     
        ebovar&& operator-=(ebovar const& other) {
            //ici, tu change la valeur de cette variable
            return *this;
        }
    };
     
    ebovar operator+(ebovar const& a, ebovar const& b) {
        return ebovar(a)+=ebovar(b);
    }
     
    ebovar operator-(ebovar const& a, ebovar const& b) {
        return ebovar(a)-=ebovar(b);
    }
     
     
    int main() {
    	ebovar _a = 8;
    	int _b = 5;
    	ebovar _c = 5.1f;
    	int _d = int(_a + _b + _c);
    	printf("%d\n", int(_d));
    }

    Regarde comment est implémenté optional. (éventuellement, utilise optional-lite)
    Je t'invite à utiliser le concept de "tagged union".
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Je suis toujours inquiet lorsqu'on me propose l'autre chemin

    Bon. A part ça, cela ton code ne compile toujours pas.
    Je vais essayer d'avancer puis je posterai ma version histoire de voir s'il y a moyen de faire mieux.

    mon objectif étant que mon variant gère les entiers, les flottants et les string
    pour le moment je ne gère que l'opérateur + qui en cas d'argument de type string fait une concaténation

    genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	ebovar _a = (ebovar)10;
    	ebovar _b = (ebovar)12;
    	ebovar _chaine = (ebovar)(const char *)"Hello 10 + 12 = " + (_a + _b);
    	echo (_chaine);
    Evidement cela doit écrire au final:
    Hello 10 + 12 = 22

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Je vais réfléchir avec un compilateur.
    Je te proposerai une version plus complète et concrête de ce que je propose.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    ca roule. merci

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

Discussions similaires

  1. surcharge de fonction
    Par BigNic dans le forum C++
    Réponses: 2
    Dernier message: 21/03/2006, 19h57
  2. API HOOK, Dump dll, Surcharge de Fonction
    Par MicroAlexx dans le forum Windows
    Réponses: 2
    Dernier message: 30/12/2005, 11h39
  3. [MFC] Surcharger des fonctions de CView
    Par Philippe320 dans le forum MFC
    Réponses: 2
    Dernier message: 22/11/2005, 22h24
  4. singleton, polymorphisme, et surcharge de fonction
    Par legend666 dans le forum C++
    Réponses: 11
    Dernier message: 14/11/2005, 10h27
  5. Surcharge de fonction d'un edit dynamique
    Par Tartar Ukid dans le forum C++Builder
    Réponses: 4
    Dernier message: 13/10/2003, 12h56

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