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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    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
    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 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
    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 éclairé
    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
    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
    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 éclairé
    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
    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 : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    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 averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    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
    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
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 035
    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

  10. #10
    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
    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