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 :

[C++] Pointeur sur fonction ou foncteur ?


Sujet :

Langage C++

  1. #1
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut [C++] Pointeur sur fonction ou foncteur ?
    Bonjour à tous .

    Je n'ai jamais utilisé de pointeur sur fonction ou de foncteur, seulement je vais en avoir besoin. J'ai lu que les foncteurs étaient bien plus rapides dans la plupart des cas, sauf que les pointeurs sur fonction ont l'air bien plus simple à implémenter et dans mon cas je ne sais pas si cela ferait une vraie différence au niveau du temps d'exécution.

    J'ai une classe Ncomputation avec entre autres 3 fonctions membres
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    double Ncomputation::f220(double a,double b,double c) const;
    double Ncomputation::f022(double a,double b,double c) const;
    double Ncomputation::f220(double a,double b,double c) const;
    Dans une autre fonction membre j'ai besoin de choisir quelle fonction membre j'utilise en fonction d'un paramètre.
    A première vue, je pensais utiliser :
    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
    double Ncomputation::calc(unsigned int axis) const
    {
        // Initialization
        double result=0.;
        double(*f)(double,double,double)=f220;
     
        // Select the function
        switch(axis)
        {
            case 1 : f=f022; break;
            case 2 : f=f202; break;
            case 3 : f=f220; break;
            default : f=f220;
        }
     
        // (Ici j'utilise f pour calculer le résultat)
        // (Ici j'utilise f pour calculer le résultat)
     
        // Return
        return result;
    }
    Déjà est-ce que ma syntaxe d'utilisation d'un pointeur sur fonction est bonne ? Ensuite est-ce que l'utilisation de foncteur aurait un réel intérêt dans mon cas (notamment au niveau du gain de performances) ou absolument aucun (et si oui, pourquoi ?)).

    Merci beaucoup

  2. #2
    Membre chevronné
    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 : 43
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Attention, un pointeur sur fonction membre n'a pas la meme signature qu'un pointeur de fonction.
    Et la pourquoi n'ecris tu pas simplement un appel au f220 et consoeurs qui sont des membres de ta classe ?

  3. #3
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut
    Ok, dans ce cas, quelle syntaxe serait correcte ?

    Si je pouvais faire un appel "unifié" à f220 et consoeurs en fait ça m'arrangerait bien (ce pourquoi je désire utiliser un pointeur sur fonction membre), parce qu'ensuite ma fonction f (qui est égale soit à f220, f022 ou f202) est impliquée dans des calculs "biens bourrins".

    Merci beaucoup.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Kaluza Voir le message
    Ok, dans ce cas, quelle syntaxe serait correcte ?
    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
    double Ncomputation::calc(unsigned int axis) const
    {
        // Initialization
        double result=0.;
        double (Ncomputation::*f)(double,double,double)const=&Ncomputation::f220;
     
        // Select the function
        switch(axis)
        {
            case 1 : f=&Ncomputation::f022; break;
            case 2 : f=&Ncomputation::f202; break;
            case 3 : f=&Ncomputation::f220; break;
            default : f=&Ncomputation::f220;
        }
     
        // (Ici j'utilise f pour calculer le résultat)
        (this->*f)(1.,2.,3.);
        // (Ici j'utilise f pour calculer le résultat)
     
        // Return
        return result;
    }

    Citation Envoyé par Kaluza Voir le message
    J'ai lu que les foncteurs étaient bien plus rapides dans la plupart des cas


    L'avantage des foncteurs c'est qu'en étant plus générique ils facilitent l'évolution.
    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
     
    stuct Ncomputation
    { 
    /* [...] */
    template<class foncteur_t_>
    double calcul_effectif(foncteur_t_ f_)const
    {
        return f_(1.,2.,3.);
    }
     
    double Ncomputation::calc(unsigned int axis) const
    {
        // Initialization
        double result=0.;
        double (Ncomputation::*f)(double,double,double)const=&Ncomputation::f220;
     
        // Select the function
        switch(axis)
        {
            case 1 : f=&Ncomputation::f022; break;
            case 2 : f=&Ncomputation::f202; break;
            case 3 : f=&Ncomputation::f220; break;
            default : f=&Ncomputation::f220;
        }
     
        return calcul_effectif(boost::bind(f,this,_1,_2,_3));
    }
    Puis un beau jour, apparait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double new_function(double,double,double);
    Peu de code à modifier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        Ncomputation a;
        a.calc(1);
        a.calc(2);
        a.calc(3);
        a.calc(17);
        a.calcul_effectif(new_function);// Ca marche avec une nouvelle fonction !!

  5. #5
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut
    Merci mille fois pour cette réponse très détaillée
    Tout est bcp plus clair maintenant !!!

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Bonjour

    Je me permet de m'incruster dans ce post pour poser une question concernant ce problème (je ne suis pas spécialiste de la méta programmation)

    Dans un tel cas (fonction appelée plusieurs fois dans un gros calcul, nombre de fonctions possible limitées et connues à la compilation), n'est-il pas préférable d'inliner la fonction appelée (en forçant l'inline ?) pour éviter l'appel de fonction et en utilisant les templates pour éviter de devoir réécrire plusieurs fois le même 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
    20
    21
    22
    23
    24
    struct F022
    {
       inline double f(double a,double b,double c) const;
    }
     
    struct F220
    {
       inline double f(double a,double b,double c) const;
    }
     
    struct F202
    {
       inline double f(double a,double b,double c) const;
    }
     
    template <typename F>
    double calc(unsigned int axis) const
    {
       // on réalise le calcul en utilisant F::f()
    }
     
    typedef calc<F022> calc022;
    typedef calc<F202> calc202;
    typedef calc<F220> calc220;
    Peut-on gagner en rapidité avec un tel code en cas de nombreux appels à la fonction ?

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    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
     
    stuct Ncomputation
    { 
    /* [...] */
    template<class foncteur_t_>
    double calcul_effectif(foncteur_t_ f_)const
    {
        return f_(1.,2.,3.);
    }
     
    double Ncomputation::calc(unsigned int axis) const
    {
        // Initialization
        double result=0.;
        double (Ncomputation::*f)(double,double,double)const=&Ncomputation::f220;
     
        // Select the function
        switch(axis)
        {
            case 1 : f=&Ncomputation::f022; break;
            case 2 : f=&Ncomputation::f202; break;
            case 3 : f=&Ncomputation::f220; break;
            default : f=&Ncomputation::f220;
        }
     
        return calcul_effectif(boost::bind(f,this,_1,_2,_3));
    }
    Salut. Pourquoi as-tu ceci ? Pourrais-tu elaborer sur cet appel de boost::bind ? Particulierement ce this ?

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par mailaka Voir le message
    Salut. Pourquoi as-tu ceci ? Pourrais-tu elaborer sur cet appel de boost::bind ? Particulierement ce this ?
    Tes fonctions sont des fonctions membres de la classe. Elles ont donc besoin d'un objet de ta classe pour être appelées. Avec boost::bind on construit un foncteur dont le premier argument, l'instance de la classe, est 'lié' au moment de la construction avec this. Ensuite, on peut l'utiliser comme une fonction avec 3 arguments double uniquement.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Tes fonctions sont des fonctions membres de la classe. Elles ont donc besoin d'un objet de ta classe pour être appelées. Avec boost::bind on construit un foncteur dont le premier argument, l'instance de la classe, est 'lié' au moment de la construction avec this. Ensuite, on peut l'utiliser comme une fonction avec 3 arguments double uniquement.
    Merci. Sur les exemples que j'ai pu voir, les fonctions n'etaient pas des fonctions membres donc pas de specification particuliere pour this. Se retrouve-t-on dans ce cas si la fonction membre etait statique, a priori pas besoin de this ?

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Dans l'exemple que j'avais proposé, on avait besoin d'un this car f022, f202 et f220 étaient des fonctions membres non statiques de Ncomputation. Si tes fonctions sont des fonctions statiques ou des fonctions libres, alors effectivement tu n'as pas besoin de lier le 'this'.
    bind permet de lier d'autres arguments. Si ta fonction accepte plus d'arguments que celle du foncteur que tu veux créer, et si tu connais les arguments au moment de la construction de ton foncteur, et éventuellement si l'ordre n'est pas le même, boost.bind te permet de construire un foncteur qui présentera la signature que tu souhaites.

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    [...]
    Je pense que son problème est de choisir la fonction à l'exécution et non sur un paramètre connu à la compilation. S'il s'agit bien d'un dynamisme à l'exécution, inline et template n'apporteront pas d'optimisation particulière sur le choix spécifique de la fonction.

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par 3DArchi Voir le message


    L'avantage des foncteurs c'est qu'en étant plus générique ils facilitent l'évolution.
    Il permet aussi au compilateur de faire des optimisation. Par exemple inliné le tous et ne plus avoir d'appel de fonction.

    C'est ce qui explique la différence entre qsort et std::sort+foncteur.
    http://www.tilander.org/aurora/2007/...and-qsort.html

  13. #13
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par yan Voir le message
    Il permet aussi au compilateur de faire des optimisation. Par exemple inliné le tous et ne plus avoir d'appel de fonction.

    C'est ce qui explique la différence entre qsort et std::sort+foncteur.
    http://www.tilander.org/aurora/2007/...and-qsort.html
    Et encore en plus de cela, un foncteur peut garder et maintenir un état suite à plusieurs appels à son operator(), sans se trimballer une variable globale ou ce genre de pourriture.

Discussions similaires

  1. Réponses: 10
    Dernier message: 03/02/2005, 13h09
  2. Réponses: 5
    Dernier message: 12/01/2005, 20h58
  3. pointeurs sur fonction en C++
    Par cemoi dans le forum C++
    Réponses: 7
    Dernier message: 29/11/2004, 13h19
  4. [langage] Pointeur sur fonction
    Par Fanch.g dans le forum Langage
    Réponses: 2
    Dernier message: 02/10/2004, 10h43
  5. Declaration de fonction retournant un pointeur sur fonction
    Par pseudokifaitladifférence dans le forum C
    Réponses: 5
    Dernier message: 11/08/2003, 19h37

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