2017-06-28 6 views
2

Disons que j'ai une classe avec trois fonctions membres, comme suit:Passe Membre Fonction en tant que paramètre à d'autres fonctions membres (C++ 11 <function>)

#include <iostream> 
#include <functional> 

class ClassName 
{ 
    public: 
    double add(double a, double b); 
    double intermediate(double a, double b, std::function<double (double,double)> func); 
    double combiner(double a, double b); 
}; 

double ClassName::add(double a, double b) 
{ 
    return a+b; 
} 

double ClassName::intermediate(double a, double b, std::function<double (double,double)> func) 
{ 
    return func(a, b); 
} 

double ClassName::combiner(double a, double b) 
{ 
    return intermediate(a, b, add); 
} 

int main() 
{ 
    ClassName OBJ; 
    std::cout << OBJ.combiner(12, 10); 
} 

Ce que je suis désireux de faire est de passer le membre fonction "ajouter" à la fonction membre "intermédiaire" qui est alors appelée par "combineur". Cependant, je ne pense pas que j'utilise la bonne syntaxe, parce que quand j'essaie de compiler ceci, j'obtiens une erreur disant "syntaxe non-standard, utilisez '&' pour créer un pointeur vers un membre." Je ne suis pas très sûr de ce qui ne va pas, parce que cette méthode fonctionne parfaitement si ces fonctions ne sont pas des fonctions membres dans une classe (juste des fonctions régulières définies dans l'espace de noms). Alors est-il possible de passer une fonction membre à une autre fonction membre?

+1

'retour intermédiaire (un , b, [ceci] (double x, double y) {return add (x, y);}); ' –

Répondre

2

ClassName::add est une fonction membre non statique, une instance de ClassName est nécessaire pour l'appel; il ne peut pas être utilisé comme argument pour std::function<double (double,double)> directement.

Vous pouvez utiliser lambda et capturer this (comme @Igor Tandetnik a commenté):

return intermediate(a, b, [this](double x, double y) { return add(x, y); }); 

ou utiliser std::bind et lier pointeur this:

return intermediate(a, b, std::bind(&ClassName::add, this, _1, _2)); 

ou faire ClassName::add une fonction membre statique ou une fonction non-membre (il peut être parce qu'il n'utilise aucun membre de ClassName). par exemple.

class ClassName 
{ 
    public: 
    static double add(double a, double b); 
    ... 
}; 
+0

Merci beaucoup, ce n'était pas quelque chose que j'avais déjà réalisé. Je vous en suis reconnaissant! – JohnTravolski

1

Si vous voulez vraiment passer la fonction de membre, vous avez besoin d'un member function pointer

class ClassName 
{ 
    public: 
    double add(double a, double b); 
    using Combiner = double (ClassName::*)(double, double); 
    double intermediate(double a, double b, Combiner); 
    double combiner(double a, double b); 
}; 

Cela changera légèrement la mise en œuvre de intermediate et combiner

double ClassName::intermediate(double a, double b, Combiner func) 
{ 
    return (this->*func)(a, b); 
} 

double ClassName::combiner(double a, double b) 
{ 
    return intermediate(a, b, &ClassName::add); 
} 
+0

@songyuanyao Bien sûr, idiot moi. – HeroicKatora

+0

Merci, c'est aussi une très bonne solution. J'apprécie vraiment cela! – JohnTravolski

+0

@JohnTravolski Sachez simplement que std :: function a généralement une grosse surcharge, à la fois pour l'exécution et pour la mise en page du compilateur et de l'objet. Par rapport à ceux-ci, les membres-pointeurs sont très compilateurs et ont l'espace requis pour tout nombre entier. – HeroicKatora