2010-09-01 9 views
11

Est-ce que C++ 11 fournit des délégués?Déléguer en C++ 11

Sinon, quelle est la meilleure façon (la plus efficace) de faire quelque chose de similaire en C++? Boost.Signals? FastDelegate? Autre chose?

+0

Quel est le problème avec des pointeurs de fonction? – alternative

+0

Je ne peux pas l'utiliser avec la méthode de classe:/ – dot222

+0

oui vous pouvez http: //www.parashift.com/C++ - faq-lite/pointers-to-members.html mais il y a probablement de meilleures choses à utiliser, par ex. Les fonctions C++ n'ont pas besoin d'être des méthodes, ou vous pouvez transformer la classe en un foncteur –

Répondre

14

Vous pouvez obtenir la sémantique comme délégué en utilisant bind pour lier une fonction membre à une instance de classe:

#include <functional> 

struct C 
{ 
    void Foo(int) { } 
}; 

void Bar(std::function<void(int)> func) 
{ 
    func(42); // calls obj.Foo(42) 
} 

int main() 
{ 
    using namespace std::placeholders; 

    C obj; 
    Bar(std::bind(&C::Foo, obj, _1)); 
} 

Dans cet exemple, Bar() prend tout ce qui a un seul paramètre int et qui retourne void.

Dans main(), nous lions un pointeur à la fonction membre C::Foo à l'instance de C nommée obj. Cela nous donne un objet qui peut être appelé avec un seul paramètre int et qui renvoie void.

Nous appelons Bar() avec cet objet et Bar() prend l'appel obj.Foo(42).

+0

+1, ou vous pouvez simplement transformer C en foncteur. –

+0

@jk: Seulement parfois. Evidemment dans ce cas vous pourriez, mais je n'ai pas beaucoup de classes dans mon application qui n'ont qu'une seule fonction membre :-) –

-1

Le mécanisme C a toujours été fonction pointeur & baton (sauf pour qsort() et bsearch() qui n'a pas pris de témoin).

Donc, on passerait toujours l'objet de classe comme le bâton.

.: par exemple

class tp { 
    public: 
     tp() { n = 0; } 
     void m(int z) { printf("%d is %d\n", n++, z++); } 
     int n; 
}; 

void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton) 
{ 
    for (int i = 0; i < cnt; i++) 
     handler(opx[itm], baton); 
} 

/* You would need to provide this stub -- potentially templateable */ 
void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); } 

/* used like so: */ 
int main() 
{ 
    int array[7]; 

    //... 
    tp cx; 
    higher_func(array, 7, translate_baton, &cx); 
} 
+5

Cette question ne concerne pas C: le mécanisme C est disponible en C++ mais cela ne le rend pas la meilleure option. –

+0

Je fais beaucoup de travail avec les délégués dans .NET et croyez-moi, cela m'aurait épargné du temps sur le chemin des délégués plutôt que l'inverse. – Joshua

0

Vous ne devez pas nécessairement attendre C++ 0x. Vous pouvez également implémenter des délégués dans la norme C++ 03 actuelle. Vous devez simplement surcharger l'opérateur(), de sorte que vous pouvez appeler MyObjectFunctor functor; functor(); et puisque le foncteur est un objet, vous pouvez le passer en tant que délégué/objet dans les fonctions;

La version actuelle de la STL définit l'en-tête <algorithm> qui fournit des fonctions prêtes à être utilisées avec Functors/Lambdas/Delegates.

exemple simple d'un foncteur.

struct FunctorDelegate 
{ 
    // as so to delegate as a function that takes an int input 
    void operator()(int) 
    { 
     // do what I want 
    } 
}; 

int main() 
{ 
    //... do some stuffs with an std::vector<int> aRange; 
    FunctorDelegate functor; 
    std::for_each(aRange.begin(), arange.end(), functor); 
} 
+0

Ce que les délégués peuvent faire est la possibilité de stocker, par exemple, 'int A :: func1 (int, int)' ou 'int B :: func2 (int, int)' dans une variable (disons 'f'), donc qu'il pourrait s'appeler comme int int = f (a, 12, 34), ou int int2 = f (b, 42, 24); Dans votre exemple, le foncteur peut être appelé, mais il ne peut pas être traité comme une abstraction du type de fonction 'void (int)'. –

2

Vous n'avez pas besoin de C++ 0x. dans <functional> vous avez bind1stbind2ndmem_fun et mem_fun_ref. Vous avez également Boost.Bind qui généralise toutes les fonctions ci-dessus (IIRC).

Voulez-vous profiter de la mémoire ...

vector<Foo> foo = makeVector(); 
vector<Foo*> foop = makeVectorP(); 
vector<Bar> bar1,bar2,bar3,bar4; 
transform(foo.begin(), foo.end(), back_inserter(bar1), mem_fun_ref(&Foo::getBar)); 
transform(foop.begin(), foop.end(), back_inserter(bar2), mem_fun(&Foo::getBar)); 
transform(foo.begin(), foo.end(), back_inserter(bar3), bind1st(&bar_from_foo)); 
transform(foo.begin(), foo.end(), back_inserter(bar4), boost::bind(&bar_from_foo, _1)); 
+6

bind1st, bind2nd, mem_fun et mem_fun_ref sont obsolètes dans C++ 11. –

1

Bien que std::function fonctionne bien, je voudrais souligner ce joli morceau de code délégué, écrit here (y compris l'utilisation d'exemple!). Après les références et les réponses, vous pouvez lire tout sur la façon dont cette classe Delegate est construite et pourquoi il peut être plus rapide que std::function.

Notez également ma question here un problème que je rencontrais avec sur VS 2015.