9
votes

Callbacks orientés objet pour C ++?

Y a-t-il une bibliothèque qui me permet de créer facilement et facilement des rappels orientés objet en C ++?

La langue Eiffel, par exemple, a le concept d'agents qui fonctionnent plus ou moins comme celui-ci: < PRE> XXX

La sortie sera la suivante: Salut du bar! 3 salut de foo!

SO - L'agent permet de capsuler un organe membre dans un objet, donnez-le sur certains paramètres d'appel prédéfini (HI de FOO), spécifiez les paramètres ouverts (?) Et transmettez-le Pour un autre objet qui peut ensuite l'appeler plus tard.

Étant donné que C ++ ne permet pas de créer des pointeurs de fonction sur des fonctions de membre non statiques, il semble que cela ne semble pas que fonctionnait quelque chose d'aussi facile à utiliser en C ++. J'ai trouvé des articles avec Google sur des rappels orientés objet en C ++, cependant, je suis en fait à la recherche de fichiers de bibliothèque ou d'en-tête, je peux tout simplement importer, ce qui permettez-moi d'utiliser une syntaxe élégante similaire.

Quelqu'un a quelque part Conseils pour moi?

merci!


2 commentaires

Je ne sais pas que je comprenne complètement votre syntaxe mais boost :: lid peut être utilisé pour emballer à la fois des fonctions et des fonctions de membre avec une interface appropriée dans un objet. boost.org/doc/libs/1_44_0/libs/ Bind / ...


Hey! Oui, je pense que c'est ce que je cherche. Malheureusement, je ne peux pas compiler boost pour l'iPhone (en développement sur l'iPhone). J'ai lu que cela est également possible de faire avec STL. Quelqu'un peut-il peut-être expliquer comment?


6 Réponses :


2
votes

C ++ permet aux orientateurs de la fonction sur les objets des membres.
Voir ici pour plus de détails.
Vous pouvez également utiliser Boost.Signals ou boost.signals2 (Depanding si votre programme est multithread ou non ).


4 commentaires

Oui, mais seulement des fonctions de membre statique. Mais je veux que l'objet lui-même soit notifié


Non, aucune fonction membre peut être un pointeur à une fonction membre.


@MAT I Insistez parce que le tapis ne semble pas la saisir: C ++ permet aux membres de la fonction non statique des membres. Cependant, la manière la plus intelligente de faire ce que vous voulez, c'est un foncteur (en effet, il s'agit simplement de définir l'opérateur de parenthèses afin que vos objets puissent se comporter comme une fonction) comme des méthodes de méthodes.


@Mat Voici un exemple de Litte: Classe A {Public: Void Foo () {};}; Typedef (void) (a :: *) () pfuncnoncétatique; A A; PfunConStatic Func = A :: FOO; une. (* Func) (); J'ai peut-être fait des erreurs, je n'ai pas essayé de compiler, mais c'est plus ou moins l'esprit de la syntaxe pour les pointeurs de fonction non constitutifs.



15
votes

Le moyen le plus OO d'utiliser des rappels dans C ++ consiste à appeler une fonction d'une interface, puis à passer une implémentation de cette interface.

#include <iostream>

class Interface
{
  public:
  virtual void callback() = 0;
};

class Impl : public Interface
{
  public:
  virtual void callback() { std::cout << "Hi from Impl\n"; }
};

class User
{
  public:
  User(Interface& newCallback) : myCallback(newCallback) { }

  void DoSomething() { myCallback.callback(); }

  private:
  Interface& myCallback;
};

int main()
{
  Impl cb;
  User user(cb);
  user.DoSomething();
}


0 commentaires

1
votes

Il y a diverses bibliothèques qui vous permettent de faire cela. Découvrez Boost :: Fonction.

ou essayez votre propre implémentation simple: xxx

utilisation: xxx


0 commentaires

1
votes

Entrant l'idée des fonctions - Utilisez STD :: TR1 :: Fonction et boost :: Liez pour construire les arguments à ce point avant de l'enregistrer.


0 commentaires

0
votes

Il existe de nombreuses possibilités en C ++, la question étant généralement une syntaxe.

  • Vous pouvez utiliser le pointeur pour fonctionner lorsque vous n'aurez pas besoin d'état, mais la syntaxe est vraiment horrible. Cela peut être combiné avec boost :: lid pour un plus de plus ... Syntaxe (*)
  • Je corrige votre fausse hypothèse, il est en effet possible d'avoir un pointeur à une fonction membre, la syntaxe est tellement gênante que vous allez fuir (*)
  • Vous pouvez utiliser des objets de fonctionnement, fondamentalement, un fonctionnement est un objet qui surcharge l'opérateur () , par exemple VOID Foncteur :: opérateur () (int A) const; , parce que c'est un objet, il a un état et peut dériver d'une interface commune
  • Vous pouvez simplement créer votre propre hiérarchie, avec un nom plus agréable pour la fonction de rappel si vous ne voulez pas aller sur la route de surcharge de l'opérateur
  • Enfin, vous pouvez tirer parti des installations C ++ 0X: std :: Fonction + Les fonctions Lambda sont vraiment géniales en matière d'expressivité.

    J'apprécierais une critique sur la syntaxe Lambda;) xxx

    bien sûr, func n'est viable que lorsque FOO est viable (problème d'étendue), vous pouvez copier foo à l'aide de [= foo] pour indiquer PASS par valeur au lieu de passer par référence.

    (*) Tutoriel obligatoire sur les pointeurs de fonction


0 commentaires

5
votes

Les gens utilisent généralement l'un des différents modèles:

héritage. C'est-à-dire que vous définissez une classe abstraite qui contient le rappel. Ensuite, vous prenez un pointeur / référence à cela. Cela signifie que tout le monde peut hériter et fournir ce rappel. P> xxx pré>

héritage à nouveau. C'est-à-dire que votre classe racine est abstraite et l'utilisateur hérite de celui-ci et définit les rappels, plutôt que d'avoir une classe de béton et des objets de rappel dédiés. P> xxx pré> encore plus héritage- statique. De cette façon, vous pouvez utiliser des modèles pour modifier le comportement d'un objet. Il est similaire à la deuxième option, mais fonctionne à l'heure de compilation au lieu du temps d'exécution, ce qui peut générer divers avantages et récidives, en fonction du contexte. P>

class Foo {
    virtual ... Call(...) = 0;
    virtual ~Foo();
};
class Base {
    std::auto_ptr<Foo> callback;
    template<typename T> Base& SetCallback(T t) {
        struct NewFoo : Foo {
             T t;
             NewFoo(T newt) : t(newt) {}
             ... Call(...) { return t(...); }
        };
        callback = new NewFoo<T>(t);
        return this;
    }
    Foo* GetCallback() { return callback; }
    void dosomething() { callback->Call(...); }
};


0 commentaires