передать вызываемый объект в функцию-член - PullRequest
0 голосов
/ 06 августа 2009
  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();
  }

Я хочу связать закрытый член _a Data с функцией-членом Display, но я получаю ошибки компиляции, говорящие, что мои типы аргументов не совпадают, когда я вызываю d.Register, что я делаю неправильно? Благодаря.

Ответы [ 3 ]

4 голосов
/ 06 августа 2009

То, что вы пытаетесь сделать, не совсем понятно, но я предполагаю, что «bind» - это boost :: bind (или tr1 :: bind).

Пара проблем с привязкой (Display :: SomeTask, this, _1):

  • Это должно быть & Display :: SomeTask
  • Заполнитель _1 не имеет смысла, потому что это создает унарный объект функции и:
    • Display :: SomeTask не принимает аргументов
    • Action :: operator () не принимает аргументов

Используя Boost.Function и Boost.Bind, вот что вы могли бы написать, чтобы получить то, что, как мне кажется, вы пытаетесь сделать:

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();
};
1 голос
/ 06 августа 2009

Я не вижу, что возвращает 'bind', но я абсолютно уверен, что это не совместимо с классом Action. Также вы используете «копировать семантику», поэтому, если в Action есть пустая имплементация, вы никогда не получите желаемого. Попробуйте изменить Register (Action * action) и разрешить 'bind' вернуть некоторый потомок класса Action.

Также рассмотрите возможность перехода на шаблоны - чем вы вообще можете исключить класс Action

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

В этом случае вы можете использовать классы с переопределенным оператором () как функции без аргументов.

0 голосов
/ 06 августа 2009

Сначала вы должны использовать &Display::SomeTask и указать Register тип возврата, а затем это зависит от ваших потребностей

  • Оболочка должна вызывать SomeTask на *this: пропустить _1.
  • Оболочка должна вызывать SomeTask для переданного Display объекта: Shift _1 вместо this.

Затем boost::bind возвращает некоторый сложный синтезированный тип, который будет вызывать указанную функцию. Вам нужен способ его хранения, где boost::function пригодится. Вот как это можно сделать

  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();
  }

Тогда это должно работать.

...