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

Langage C++ Discussion :

[HowTo : surcharge] Préciser une fonction membre


Sujet :

Langage C++

  1. #1
    Membre averti
    Inscrit en
    Janvier 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 34
    Par défaut [HowTo : surcharge] Préciser une fonction membre
    Bonjour,

    Voilà, dans le cadre d'un projet, j'ai un pointeur sur fonction membre que je dois utiliser comme paramètre d'une méthode. Je veux que ce pointeur pointe sur une méthode qui bénéficie de nombreuses surcharges, mais j'en veux une en particulier.
    Je cherche à savoir si c'est possible, est-ce que ça l'est ?

    Merci d'avance.

  2. #2
    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 : 51
    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
    Par défaut
    Oui, c'est possible. Il va utiliser le type de ton pointeur pour déterminer quelle version de la surcharge prendre.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre averti
    Inscrit en
    Janvier 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 34
    Par défaut
    Oui, en fait, il faut que je l'assigne avant à mon pointeur de fonction au lieu de le faire à la volée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    forAllVertex(&Vertex::setColor, r, g, b, a);
    Je dois plutôt faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    typedef void (Vertex::* pf4)(float, float, float, float);
    pf4 pf = &Vertex::setColor
    forAllVertex(pf, r, g, b, a);
    Mais je voulais savoir si il était possible de le spécifier à la volée... Je pense pas.
    Parce que je dispose d'une surcharge pour forAllVertex dans son nombre d'arguments. Et j'ai défini des types pf1, pf2, pf3, etc.
    Et je n'ai malheureusement pas le droit d'utiliser les templates variadiques (si quelqu'un sait quand ce sera adopté la nouvelle norme 0x je suis preneur).

    Sachant que setColor est lui-même surchargé...

  4. #4
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Ylvin Voir le message
    )(si quelqu'un sait quand ce sera adopté la nouvelle norme 0x je suis preneur).
    c'est fait depuis un petit moment

  5. #5
    Membre averti
    Inscrit en
    Janvier 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 34
    Par défaut
    Merde, c'est que c'est vrai en plus...

    Il y a des baffes qui se perdent. -_-
    Mais j'ai l'impression que Visual C++ ne le supporte toujours pas entièrement. C'est sans doute pour cette raison qu'ils continuent à me prendre la tête avec l'ancienne norme.
    CF : http://wiki.apache.org/stdcxx/C++0xCompilerSupport

  6. #6
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    typedef void (Vertex::* pf4)(float, float, float, float);
    forAllVertex(pf4(&Vertex::setColor), r, g, b, a);

  7. #7
    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 : 51
    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
    Par défaut
    Il faudrait que je me plonge dans la norme pour donner une réponse, car là ta situation n'est pas triviale.

    Mais pourquoi faire autant de surcharges de forAllVertex ? Une seule version templatisée à un seule argument que tu utilises éventuellement en utilisant [boost/std]::bind ou un lambda devrait aboutir au même, non ?

    Ce qui m'a fait penser que bind a probablement le même problème que toi... Et en regardant, je suis tombé sur http://www.boost.org/doc/libs/1_48_0...err_overloaded mais l'exemple qu'ils donnent est avec le même nombre d'arguments dans les deux overloads.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre averti
    Inscrit en
    Janvier 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 34
    Par défaut
    Merci Ekleog. J'ignorai (ou bien j'avais oublié) qu'on pouvait faire ce genre de chose. C'est précisément ce genre de truc que j'avais en tête.

    @ JolyLoic : Je suis pas super au point avec Boost, bind, etc. Ce sont des lacunes dont j'ai conscience, mais je suis un peu débordé. Pour le coup, je suis pas certain de comprendre tout ce que tu indiques, et je vois pas trop comment bind pourrait remplacer le bidule ?
    Après, boost, c'est quelque chose d'assez mystérieux dans son fonctionnement pour moi et j'ai peur que l'utilisation de bind à ce niveau là (centaine d'appels à la seconde possiblement) me coûte très cher en terme de performance...
    Si tu pouvais m'expliquer, je pourrai peut-être mieux te répondre, et accessoirement revoir mes méthodes d'implémentation.

  9. #9
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Ylvin Voir le message
    Merde, c'est que c'est vrai en plus...

    Il y a des baffes qui se perdent. -_-
    Mais j'ai l'impression que Visual C++ ne le supporte toujours pas entièrement. C'est sans doute pour cette raison qu'ils continuent à me prendre la tête avec l'ancienne norme.
    CF : http://wiki.apache.org/stdcxx/C++0xCompilerSupport
    oui, malheureusement VS (2010) ne gère pas les variadic templates
    et ça ne semble pas prévu pour VS 2011 non plus :/
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  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 : 51
    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
    Par défaut
    En gros, quand la fonction forAllVertex(&Vertex::setColor, r, g, b, a); va appeler la fonction Vertex::setColor, elle va tout le temps le faire avec les mêmes valeurs pour r, g, b et a, alors que la valeur du vertex "this" va elle changer à chaque appel.

    Donc, pour moi, la spécification de ce qu'attend forAllVertex est un foncteur prenant un vertex en paramètre, et sans valeur de retour. Il n'y a pas besoin de 50 versions de forAllVertex, il suffit juste d'adapter des fonctions qui auraient des paramètres similaires mais différents au moment de les passer à un forAllVertex unique.

    Totalement écrit à la main, ce serait :

    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
    52
    53
    54
    55
    56
    57
    58
    #include <vector>
    #include <iostream>
     
    class Vertex
    {
    public:
    	void doIt(int r, int g, int b, int a) const
    	{
    		std::cout << "doIt(int r, int g, int b, int a)" << std::endl;
    	}
    	void doIt(int r, int g, int b) const
    	{
    		std::cout << "doIt(int r, int g, int b)" << std::endl;
    	}
    	void doIt() const
    	{
    		std::cout << "doIt()" << std::endl;
    	}
    };
     
    typedef void (Vertex::*FctWith4Args)(int r, int g, int b, int a) const;
     
    struct FunctionWithRgba
    {
       FunctionWithRgba(FctWith4Args memFunPtr, int r, int g, int b, int a) :
          r(r), g(g), b(b), a(a), memFunPtr(memFunPtr)
       {}
       void operator()(Vertex const&v)
       {
    	   return ((v).*(memFunPtr))(r, g, b, a);
       }
       int r;
       int g;
       int b;
       int a;
       FctWith4Args memFunPtr;
    };
     
    template <class F>
    void forEachVertex(std::vector<Vertex> & v, F f)
    {
    	for (std::vector<Vertex>::iterator it = v.begin();
    		it != v.end() ;
    		++it)
    	{
    		f(*it);
    	}
    }
     
     
    int main()
    {
    	std::vector<Vertex> v;
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	forEachVertex(v, FunctionWithRgba(&Vertex::doIt, 0, 1, 2, 3));
    }
    Écrit avec des lambdas ce serait bien plus agréable (pour info, cette version a compilé du premier coup chez moi, ce qui n'est pas le cas de la précédente, alors qu'elle offre bien plus de souplesse...) :
    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 <vector>
    #include <iostream>
     
    class Vertex
    {
    public:
    	void doIt(int r, int g, int b, int a) const
    	{
    		std::cout << "doIt(int r, int g, int b, int a)" << std::endl;
    	}
    	void doIt(int r, int g, int b) const
    	{
    		std::cout << "doIt(int r, int g, int b)" << std::endl;
    	}
    	void doIt() const
    	{
    		std::cout << "doIt()" << std::endl;
    	}
    };
     
    template <class F>
    void forEachVertex(std::vector<Vertex> & v, F f)
    {
    	for (std::vector<Vertex>::iterator it = v.begin();
    		it != v.end() ;
    		++it)
    	{
    		f(*it);
    	}
    }
     
     
    int main()
    {
    	std::vector<Vertex> v;
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	forEachVertex(v, [=](Vertex const &v){return v.doIt(0, 1, 2, 3);});
    }
    Et enfin la version avec [boost/std]::bind (a mon avis, à utiliser principalement si le compilateur ne gère pas encore les lambdas) (je ne sais pas quel détail fait que bind trouve la bonne version de la surcharge alors que du code naïf essayant de faire pareil ne la trouve pas) :
    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
    #include <vector>
    #include <iostream>
    #include <functional> // Ou <boost/bind.hpp>
     
    class Vertex
    {
    public:
    	void doIt(int r, int g, int b, int a) const
    	{
    		std::cout << "doIt(int r, int g, int b, int a)" << std::endl;
    	}
    	void doIt(int r, int g, int b) const
    	{
    		std::cout << "doIt(int r, int g, int b)" << std::endl;
    	}
    	void doIt() const
    	{
    		std::cout << "doIt()" << std::endl;
    	}
    };
     
    template <class F>
    void forEachVertex(std::vector<Vertex> & v, F f)
    {
    	for (std::vector<Vertex>::iterator it = v.begin();
    		it != v.end() ;
    		++it)
    	{
    		f(*it);
    	}
    }
     
     
    int main()
    {
    	std::vector<Vertex> v;
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	v.push_back(Vertex());
    	forEachVertex(v, std::bind(&Vertex::doIt, std::placeholders::_1, 0, 1, 2, 3));
    }
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Membre averti
    Inscrit en
    Janvier 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 34
    Par défaut
    Malheureusement, les lambda fonctions ne sont visiblement pas acceptées par le compilateur (MINGW). Il ne reconnaît pas la syntaxe et me hurle dessus. D'ailleurs, mon IDE (QtCreator) non plus. Et visiblement, c'est pas pour de suite. Et vu que j'ai pas le droit de modifier mon environnement de travail... Bref, c'est regrettable parce que les lambda fonctions sont vraiment sympa.
    Obligé de partir sur la version boost avec Bind.

    Et maintenant, je me rends compte que son utilisation est elle aussi impossible. Le projet doit pouvoir compiler sur une machine autre que la mienne, sans que je puisse connaître à l'avance les librairies présentes ou non, et dans quelles versions. Bref, à moins de faire le porc et de joindre toute les dépendances de Boost que je voudrais utiliser à mon projet, je ne pourrai pas l'utiliser...

    En tout cas, merci beaucoup pour toutes les réponses JolyLoic. Je ne connaissais pas les lambda fonctions, ni le fonctionnement de bind. Maintenant je connais les deux. Et je me rends compte aussi qu'il me reste encore plein de choses à apprendre.
    J'utiliserai donc ta première solution, basée sur les foncteurs.

    Je met le sujet en résolu.

    EDIT: Accessoirement, pour les curieux, ça donnerait ça :
    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
     
    template <class A, class F, typename T>
    class Foncteur3
    {
    public:
        Foncteur3(F function, T r, T g, T b) : function(function), r(r), g(g), b(b) {}
     
        void    operator()(A &v) {((v).*(function))(r, g, b);}
    private:
        F       function;
        T       r;
        T       g;
        T       b;
    };
     
     
     
    class Object
    {
      typedef void (Vertex::* pf3)(float, float, float);
      typedef void (Vertex::* pf4)(float, float, float, float);
    public:
     
    void Object::exemple(float x, float y, float z)
    {
        forAllVertex(Foncteur3<Vertex, pf3 , float>(&Vertex::SelfScale, x, y, z));
    }
    private:
       std::list<Vertex>    vertex;
     
       template <class F>
       void forAllVertex(F f)
    {
        for (std::list<Vertex>::iterator it = vertex.begin(), end = vertex.end(); it != end; ++it)
        {
            f(*it);
        }
    };

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

Discussions similaires

  1. Réponses: 14
    Dernier message: 16/05/2006, 11h26
  2. Réponses: 3
    Dernier message: 29/04/2006, 13h02
  3. Réponses: 4
    Dernier message: 01/12/2005, 12h33
  4. Réponses: 3
    Dernier message: 28/11/2005, 12h15
  5. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15

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