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 :

Pointeur sur fonction membre non static


Sujet :

C++

  1. #1
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut Pointeur sur fonction membre non static
    Bonjour,

    Je vais reposer une de mes anciennes question en nuancent mon propos.
    Je dispose d'une classe Segmentation pouvant disposer de plusieurs instance d'objet.
    J'ai une classe Solver qui à pour but de résoudre un problème d'optimisation. La fonction d'évaluation est contenu dans la classe Segmentation (logique). Donc ma question est : comment appeler la fonction de l'OBJET Segmentation dans le solver.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double(*ptr)(double) = &Segmentation::ComputeMean;
    Solver goldenSearch(ptr);
    En gros je souhaite que la fonction contenue dans ptr soit la fonction ComputeMean. Lorsque le solver appelle ComputeMean il faut que la fonction utilise les données contenue dans l'instance de classe Segmentation.

    Merci d'avance,
    Robin

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    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 195
    Points : 17 163
    Points
    17 163
    Par défaut
    D'abord, tu n'es pas au bon endroit (ici, c'est le C)
    Le code ressemble à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Bidule {
    public:
        int f() const;
    };
     
    int fonction( int (Bidule::*)() f, Bidule const& b) {
        return b.*f();
    }
    Du moins, je crois que c'est ca. Les operateurs sont .* et ->*, selon que l'instance soit dans un pointeur ou non.

  3. #3
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Je suis confus. Vraiment désolé pour mon erreur de post (si un modo passe par là merci de déplacer ce poste dans C++/Débuter )

    Ton code fonctionne mais ça sous entend que Bidule soit connue de fonction.
    Je n'ai pas spécialement envie d'écrire une fonction pour chaque type que je passerais à mon Solver.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Bonjour,

    En gros tu veux que ton solver puisse exécuter une fonction membre sur n'importe quel objet ?
    - soit tu définis une classe de base Base et tu fais hériter toutes les classes contenant la fonction en question de cette classe. Puis tu demandes un pointeur sur membre de cette base (m'enfin, j'ai pas essayé, à confirmer) : double (Base::*)(double)
    - soit tu fais un bind pour "générer" une fonction que tu vas passer à ton solver. Le bind permet, quand on connaît l'objet, de "construire" une fonction non-membre à partir d'une fonction membre. Du coup ton solver prendrait un double (*)(double)

    Pas sûr d'avoir compris, en tout cas cette dernière option te permettra de passer à peu près n'importe quoi à partir du moment où tu connais l'objet au moment où tu appelles la fonction.

    Edit: en (très) gros, ça donnerait un truc comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void solve(double(*)(double));
     
    class Toto {
      // ...
      double dosomecalculation(double);
      // ...
    };
     
    // ...
    Toto obj(1, 2, "another param");
    auto f = std::bind(&Toto::dosomecalculation, &obj, _1);
    solve(f);

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    @the Hound: Es-tu sûr que bind() peut retourner des pointeurs de fonction bruts? Il me semble que ça ne retourne que des objets.

    Par contre, le retour de bind() peut être mis dans un std::function<>, donc il suffit au solver d'accepter cela au lieu d'accepter des pointeurs de fonction bruts.

  6. #6
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Je me suis dit que mon problème pourrais être résolu par l'utilisation d'un template finalement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double(Segmentation::*ptr)(double) = &Segmentation::Evaluate;
    Solver<Segmentation> goldenSearch(ptr);
    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
    #ifndef SOLVER_H_
    #define SOLVER_H_
     
    #include "MathUtils.h"
     
    template<class T>
    class Solver
    {
    private:
    	double(T::*ptr)(double);
     
    	Solver();
     
    public:
    	Solver(double(T::*ptr)(double));
     
    	double f(double x);
     
    	double goldenSectionSearch(double a, double b, double c, double epsilon);
    };
     
    #include "Solver.cpp"
     
    #endif
    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
    #ifndef SOLVER_CPP_
    #define SOLVER_CPP_
     
    #include "Solver.h"
     
    template<class T>
    Solver<T>::Solver()
    {
     
    }
     
    template<class T>
    Solver<T>::Solver(double(T::*ptr)(double))
    {
    	this->ptr = ptr;
    }
     
    template<class T>
    double Solver<T>::f(double x)
    {
    	return this->ptr(x);
    }
     
    template<class T>
    double Solver<T>::goldenSectionSearch(double a, double b, double c, double epsilon)
    {
    	double x;
    	if (c-b > b-a)
    		x = b + (2-M_PHI)*(c-b);
    	else
    		x = b - (2-M_PHI)*(b-a);
    	if (abs(c-a) < epsilon*(abs(b) + abs(x)))
    		return (c+a)/2.0;
    	if (f(x) < f(b))
    	{
    		if (c-b > b-a)
    			return goldenSectionSearch(b, x, c, epsilon);
    		else
    			return goldenSectionSearch(a, x, b, epsilon);
    	}
    	else
    	{
    		if (c-b > b-a)
    			return goldenSectionSearch(a, b, x, epsilon);
    		else
    			return goldenSectionSearch(x, b, c, epsilon);
    	}
    }
     
    #endif

  7. #7
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Pardon, j'ai effectivement oublié que ce n'était pas des fonctions qui étaient construites (pas possible en C++) mais des foncteurs. Merci Médinoc pour la remarque.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void solve(std::function<double(double)>);
    // ...

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    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 195
    Points : 17 163
    Points
    17 163
    Par défaut
    Il me semble qu'on peut aussi donner un objet définissant un operator().

    En combinant avec un PointerWrapper, ça donnerait quelque chose comme:

    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
     
    class SegmentationMeanComputer {
    private:
        Segmentation const * mine
    public:
        SegmentationMeanComputer () : mine(0) {}
        change(Segmentation * s) {
             mine = s;
        }
        double operator()(double d) {
            return mine->ComputeMean(d);
        }
    };
     
    void f(Segmentation const& seg1, Segmentation const& seg2) {
        SegmentationMeanComputer  meaner();
        Solver goldenSearch(meaner);
     
        meaner.change(seg1);
        goldenSearch.search();
     
        meaner.change(seg2);
        goldenSearch.search();
    }
    Bon, maintenant, je vais me laver les mains...

  9. #9
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Il faut vraiment que je me renseigne sur ces fameuses std::function<>. Ça a l'aire plus lisible que ma tambouille.

  10. #10
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    La solution de leternel est sûrement la plus adaptée, quoique l'équivalent d'un std::bind en un peu moins lourd.
    Plus qu'à y rajouter des templates

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    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 195
    Points : 17 163
    Points
    17 163
    Par défaut
    C'est en fait assez différent d'un bind, parce qu'on peut changer l'instance.
    Par contre, c'est sale... très sale

  12. #12
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Bin du coup ça fonctionne bien avec les templates. Il faut bien penser à passer au Solver un pointeur sur l'objet sur lequel il doit travailler.
    Merci pour vos alternatives, je vais les tester de ce pas.

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

Discussions similaires

  1. Pointeur sur fonction membre non static
    Par robinsondesbois dans le forum Débuter
    Réponses: 6
    Dernier message: 16/04/2014, 13h36
  2. [POO] Pointeur sur fonction membre et héritage
    Par MrDuChnok dans le forum C++
    Réponses: 9
    Dernier message: 20/07/2006, 17h19
  3. Pointeur sur fonction membre avec parametre
    Par Glosialabolas dans le forum C++
    Réponses: 7
    Dernier message: 06/02/2006, 02h32
  4. Réponses: 10
    Dernier message: 03/02/2005, 13h09
  5. Réponses: 5
    Dernier message: 12/01/2005, 20h58

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