2011-03-09 4 views
6

J'ai un problème probablement simple, embarassingly: passer et appeler une fonction membre dans une classe. Je sais que je veux utiliser BOOST bind (et ou function), mais je n'ai pas encore vraiment compris le concept.Pass et appeler une fonction membre (boost :: bind/boost :: fonction?)

Le code suivant compile et exécute avec le problème. Mais quand je veux changer la fonction "f3" à une fonction de classe non-statique, le plaisir commence:

#include <iostream> 
#include <inttypes.h> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

class Test 
{ 
public: 
    void f1(); 
private: 
    void f2(void (*callfunc)(uint32_t)); 
    static void f3(uint32_t x); 
}; 

void Test::f1(){ 
    f2(f3); 
} 

void Test::f2(void (*callfunc)(uint32_t)){ 
    (*callfunc)(42); 
} 

void Test::f3(uint32_t x){ 
    std::cout << "x: " << x << std::endl; 
} 

int main(int argc, char ** argv) 
{ 
    Test ct; 
    ct.f1(); 
    return 0; 
} 

Maintenant, après avoir changé

static void f3(uint32_t x); 

à

void f3(uint32_t x); 

le compilateur n'est pas heureux et me dit « erreur: aucune fonction de mise en correspondance pour l'appel à « test :: f2() » »

Après avoir lu e un certain nombre de messages SO concernant boost :: bind et boost :: function, je pense que je dois changer la définition de f2() et comment f1() appelle f2() en donnant f3() comme cible à appeler, mais à part que ... à propos de chaque combinaison de boost :: bind et boost fonction que j'ai essayé lamentablement de ne pas compiler.

Comment ai-je besoin d'écrire cela? En guise de question supplémentaire: y a-t-il de simples introductions sur boost :: bind et boost :: function? Les docs BOOST ne m'a pas vraiment aidé là-bas.

B.

Répondre

8

boost :: est une classe de modèle, qui prend une signature de fonction. Vous pouvez également utiliser function0, function1, etc.

boost::function< void(uint32_t) >

définit un « appelable » qui ressemble à une fonction, à savoir qu'il prend un seul paramètre de type uint32_t et renvoie vide.

Le modèle numéroté approprié est function1< void, uint32_t >. Ceux-ci indiquent toujours le type de retour en premier, puis les paramètres dans l'ordre.

boost::bind est une fonction très spéciale qui déduit les arguments que vous lui transmettez et crée un foncteur pour vous.

Il ne créera pas un vide (uint32_t) pour vous, il créera quelque chose qui a le modèle d'un.

donc changer votre signature à:

void f2(boost::function<void(uint32_t)>); 

Ensuite, vous pouvez l'appeler comme ceci:

f2(boost::bind(&Test::f3, this, _1)); 

Notez l'étrange _1 est un "espace réservé" dire boost :: bind où il doit mettre dans le paramètre, dans ce cas, le uint32_t

5

D'abord, je vais expliquer la raison que la suppression du static vous donne une erreur de compilation:

Jetez un oeil à cette signature:

void (*callfunc)(uint32_t) 

Ceci est un pointeur pour libérer la fonction qui prend un uint32_t et renvoie void. Lorsque f3 est déclarée à l'intérieur comme Test

void f3(uint32_t x); 

puis f3 est une fonction de membre de la classe Test qui prend un uint32_t et renvoie void. Par conséquent, il n'y a aucun f3 qui correspond au type de l'argument attendu f2.

Quant à la façon boost::function et boost::bind peut être utilisé pour fournir une solution:

void Test::f1(){ 
    boost::function<void (uint32_t)> f = boost::bind(&Test::f3, this, _1); 
    f2(f); 
} 

Mise à jour:

Enfin, en ce qui concerne un tutoriel: J'ai trouvé this utile pour l'apprentissage de foncteurs (ce qui est ce qui boost::function est et boost::bind renvoie) dans le passé. Il ne mentionne pas spécifiquement boost, mais une fois que vous comprenez ce qui se passe exactement dans un niveau inférieur, vous trouverez boost un jeu d'enfant. Fonction

+0

Vous avez fait votre correction j'étais sur le point de vous dire de faire – CashCow

+0

@CashCow: Oui, juste pris il y a quelques minutes puisque je ne l'ai pas fait compiler ceci. – Jon

+0

Si je pouvais, j'accepterais aussi votre réponse car elle contient le lien vers l'introduction du foncteur. La réponse de CashCow était un peu plus complète mais avec la signature de f2() (ce qui était assez clair pour moi à partir de votre réponse, mais peut-être pas pour d'autres). En tout cas, merci beaucoup pour la réponse et le lien. – BaCh

Questions connexes