Question

  class Action {
    public:
      void operator() () const;
  }

  class Data {
    public:
      Data();
      ~Data();
      Register(Action action) { _a = action; }

    private:
      Action _a;
   }

  class Display {
    public:
      Display(Data d) { d.Register( bind(Display::SomeTask, this, _1) ); }
      ~Display();
      void SomeTask();
  }

Je veux lier le député _A des données à une fonction de membre d'affichage, mais je reçois des erreurs de compilation en disant mes types d'arguments ne correspondent pas quand je l'appelle d.Register, qu'est-ce que je fais mal? Merci.

Était-ce utile?

La solution

Qu'est-ce que vous essayez de faire est pas tout à fait clair, mais je suppose que "lier" est boost :: bind (ou TR1 :: bind).

Un couple de problèmes avec bind (affichage :: SomeTask, ce, _1):

  • Il devrait être & Display :: SomeTask
  • L'espace réservé _1 n'a pas de sens, car cela crée un objet de fonction unaire et:
    • Affichage :: SomeTask ne prend aucun argument
    • Action opérateur :: () ne prend aucun argument

Utilisation Boost.Function et Boost.Bind, voici ce que vous pouvez écrire à acheive ce que je suppose que vous essayez de faire:

typedef boost::function<void(void)> Action;

class Data {
public:
  Data();
  ~Data();
  Register(Action action) { _a = action; }

private:
  Action _a;
};

class Display {
public:
  Display(Data d) { d.Register( bind(&Display::SomeTask, this) ); }
  ~Display();
  void SomeTask();
};

Autres conseils

Je ne vois pas ce que « lier » les retours, mais je suis absolument sûr que ce n'est pas compatible avec la classe d'action. vous utilisez également « copie sémantique », donc si l'action a implmentation vide, vous ne serez jamais désiré. Essayez changer de registre (Action d'action *), et permettre à « lier » pour revenir un enfant de la classe d'action.

Consultez également la possibilité de migrer vers des modèles - que vous pouvez même exclure la classe d'action du tout

template <class A>
class Data { ...
Register(A action)...
A _a;
...

Dans ce cas, vous pourriez être en mesure d'utiliser comme classes avec opérateur () redéfinie comme fonctions sans argument.

D'abord, vous devez utiliser &Display::SomeTask et donner Register un type de retour, et il dépend de vos besoins

  • L'emballage doit appeler SomeTask sur *this: Omettre _1.
  • L'emballage doit appeler SomeTask sur un objet Display passé: Shift _1 à la place de this.

Ensuite, boost::bind retourne un certain type de synthèse complexe qui appelle la fonction spécifiée. Vous avez besoin d'un moyen de stocker, ce qui est à portée de main où boost::function vient. Voici comment vous pouvez le faire

  class Display; // forward-declaration
  class Data {
    public:
      Data();
      ~Data();

      template<typename Action>
      void Register(Action action) { _a = action; }

    private:
      boost::function<void(Display&)> _a;
      // if wrapper should call it on `*this`
      // boost::function<void()> _a;
   }

  class Display {
    public:
      // this currently makes no sense. You pass a copy. Probably you
      // should consider pass-by-reference or processing "d" further. 
      Display(Data d) { d.Register( bind(&Display::SomeTask, _1) ); }
      // wrapper should call it on `*this`:
      // Display(Data d) { d.Register( bind(&Display::SomeTask, this) ); }
      ~Display();
      void SomeTask();
  }

Ensuite, il devrait fonctionner.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top