2010-09-24 15 views
0

Ok, ça fait longtemps que j'ai écrit en C++. et je n'ai jamais rien fait de silencieux à ce niveau élevé.passer des fonctions

Donc, fondamentalement, je dois créer une classe. Le constructeur de la classe doit prendre une référence (ou un pointeur) à une méthode d'une autre classe ou à une fonction.

Fondamentalement, j'ai une classe qui a besoin de lire occasionnellement une valeur à partir d'un évaluateur fltk (version 1.1.x), puis de modifier certaines choses sur lui-même. Chaque objet sera associé à son propre évaluateur. (ils ont aussi un lien vers un autre objet du même parent, qui après s'être mis à jour de l'évaluateur dira mettre à jour, et ainsi de suite)

Alors, comment est-ce que je passe les fonctions, dans les constructeurs?

+0

Comment savez-vous quel objet appeler la méthode transmise? Cet objet est-il déjà connu pendant la construction, ou plus tard quand vous voulez l'appeler? – fredoverflow

+0

la méthode passée ne prend aucun paramètre. Il retourne juste une valeur double qui est ce que l'évaluateur est actuellement défini. l'objet Valuator qui a la méthode que je veux transmettre a déjà été créé. –

+0

Regardez dans les fonctions standard mem_fun et mem_fun_ref. Ceux-ci peuvent faire exactement ce que vous cherchez. – JoshD

Répondre

3

Voici un exemple où une méthode de Foo est passé au constructeur Bar et plus tard invoqué sur un objet Bar donné:

struct Foo 
{ 
    int z; 

    int add(int x, int y) 
    { 
     return x + y + z; 
    } 

    int mul(int x, int y) 
    { 
     return x * y * z; 
    } 
}; 

typedef int (Foo::*foo_method)(int, int); 

struct Bar 
{ 
    foo_method m; 

    Bar(foo_method m) : m(m) {} 

    int call_on(Foo* foo) 
    { 
     return (foo->*m)(4, 2); 
    } 
}; 

int main() 
{ 
    Bar bar(&Foo::add); 

    Foo foo = { 123 }; 
    bar.call_on(&foo); 
} 

Si, d'autre part, vous savez déjà l'objet Foo à Bar temps de construction, alors Bar ne se soucie pas vraiment à quelle classe appartient la méthode. Tout ce dont il a besoin est un foncteur à appeler plus tard, et l'objet Foo peut simplement être lié par le client.

#include <functional> 

struct Bar 
{ 
    std::function<int (int, int)> f; 

    Bar(std::function<int (int, int)> f) : f(f) {} 

    int call() 
    { 
     return f(4, 2); 
    } 
}; 

using namespace std::placeholders; 

int main() 
{ 
    Foo foo = { 123 }; 
    Bar bar(std::bind(&Foo::add, &foo, _1, _2)); 

    bar.call(); 
} 

Si vous ne disposez pas d'un compilateur C++ 0x, remplacez std::bind avec std::tr1::bind ou boost::bind.

+0

C'est le dernier cas, malheureusement je suis coincé avec GCC 3.42. (dev C++), je ne veux pas mettre à jour car c'est celui que mon évaluateur utilisera aussi. Je pense que je vais porter tout l'objet juste pour accéder à ses méthodes. –

+0

@Oxi: Alors, 'Bar' sait-il au moment de la compilation quelle méthode' Foo' appeler? Dans ce cas, vous n'avez pas du tout besoin de pointeurs de fonction. – fredoverflow

1

Votre constructeur pourrait ressembler à ceci:


// convenient typedef. This is for a pointer to a function in Foo 
// The function returns void and takes no parameters. 
typedef void (Foo::*FooPtr)(); 

class Bar { 
public: 
    Bar (FooPtr foo_ptr); 
}; 

Découvrez quelques références web pour plus de détails sur la syntaxe pour pointer à des membres. C'est beaucoup plus facile si vous le connaissez d'abord.

Pour plus d'informations, consultez les fonctions mem_fun et mem_fun_ref. Ceux-ci peuvent faire ce dont vous avez besoin.

+0

En fait, il se peut qu'il ne soit pas membre d'une classe. Il pourrait être une fonction, j'ai créé aussi peu que wrapper (par exemple pour convertir les degrés en radians). –

+0

@Oxi: "il pourrait ne pas" -> il ne l'est pas? Ou voulez-vous autoriser les deux? – fredoverflow

1

La façon la plus simple de capturer cela est avec boost::function. Il peut stocker des pointeurs de fonction, mais aussi le résultat de la liaison d'une fonction membre à un objet.

Par exemple,

class Foo { 
    Foo(boost::function<int(void)>); 
}; 

vous permettra d'accepter toute source d'entiers.