Указатель на функцию-член C ++, boost :: сигналы - PullRequest
2 голосов
/ 23 августа 2011

У меня следующая ситуация (лучше в коде)

    class Foo
    {
private:
       typedef boost::signal<void ()> Signal;
       Signal signal;

public:
       void Register_SignalFunction(const Signal::slot_type& slot);
       void Unregister_SignalFunction(const Signal::slog_type& slot);
    }

    class OtherFoo
    {
       Foo foo;
public:
       OtherFoo()
       {
            foo.Register_SignalFunction(&OnSignal)    //I know I can't do this that is precisely my question.
       }

       void OnSignal();  //what to do when signal fires
     }  

Итак, вопрос в том, как передать указатель 'member-function' методу Register. Кроме того, это нормально? Что мне нужно / нужно, так это какая-то система регистрации делегатов, поэтому, если кто-нибудь сможет указать мне правильное направление, я буду признателен. Спасибо заранее.

Ответы [ 4 ]

3 голосов
/ 23 августа 2011

Как правило, вы используете Boost Bind:

foo.Register_SignalFunction (boost :: bind (& OtherFoo :: OnSignal, this));

Что здесь происходит? : -)

Метод подключения сигнала принимает функтор. Это объект, который реализует оператор (). bind получает указатели на функции (для освобождения функций или функций-членов) и возвращает функтор с правильной сигнатурой.

Также смотрите здесь:

Полный пример использования Boost :: Signals для событий C ++

и здесь:

как работает boost :: function и boost :: bind

Чтобы отключить хранилище сигналов, возвращаемое значение из connect в:

boost::signals::connection

А затем вызовите метод отключения для этого.

1 голос
/ 23 августа 2011

Как правило, вы либо делаете:

void Register_SignalFunction(const boost::function<void()> &slot) {
    signal += slot;
}

Или, как встроенная функция:

template<typename T>
void Register_SignalFunction(T &slot) {
    signal += slot;
}

Последнее может быть несколько более эффективным при удалениислой косвенности boost::function имеет - но только при условии, что boost::signal не использует boost::function внутри (что, скорее всего, и будет).Так что используйте тот, который вы предпочитаете.

0 голосов
/ 15 сентября 2017

На случай, если кому-то понадобится полный пример:

#include <iostream>
#include <boost/signals2/signal.hpp>
#include <boost/bind.hpp>
#include <boost/optional/optional_io.hpp>

#define registerEvent_(A)   registerEvent(boost::bind(A, this, _1, _2))

struct A
{
    typedef boost::signals2::signal<int (int &, int &)> EventSignal;
    typedef EventSignal::slot_type SlotType;

    void registerEvent(const SlotType & slot);
    void triggerAll(int& a1, int& a2);

    EventSignal signal_;
};

void A::registerEvent(const SlotType & slot) { signal_.connect(slot); }
void A::triggerAll(int& a1, int& a2) {std::cout << signal_(a1, a2) << "\n";}

struct B : public A
{
    B();
    int myFunc(int& a1, int& a2);
};

B::B() {
#ifdef WITHMACRO
    registerEvent_(&B::myFunc);
#else
    registerEvent(boost::bind(&B::myFunc, this, _1, _2));
#endif
}
int B::myFunc(int& a1, int& a2) { return a1 + a2 + 1; }

int main()
{
    int a1 = 2;
    int a2 = 3;
    B b;
    b.triggerAll(a1, a2);
}
0 голосов
/ 23 августа 2011

у меня получилось, после многих попыток, вот код:

GraphicsDeviceManager
{
  private:
      typedef boost::signal<void ()> DeviceLost;
      DeviceLost deviceLost;

  public:
      Register_DeviceLostHandler(const boost::function<void ()> &handler)
      {
          deviceLost.connect(slot);
      }
      Unregister_DeviceLostHandler(const boost::function<void ()> &handler)
      {
          //deviceLost.disconnect(slot); 
      }
}

class GameBase
{
  private:
    GraphicsDeviceManager* graphics;

   public:
       GameBase()
       {
          graphics = new GraphicsDeviceManager();
          graphics->Register_DeviceLostHandler(boost::bind(&GameBase::OnDeviceLost, this));
       }
       void OnDeviceLost()
       {
           //do some stuff
       }
}

хорошо, этот код работает, как и должно быть, за одним исключением, если я раскомментирую инструкцию deviceLost.disconnect (handler), я получаю ошибки компиляции, такие как: ошибка C266 «boost :: operator ==»: 4 перегрузки имеют похожие преобразования.

Итак, почему это происходит? Вы знаете какой-нибудь другой способ выполнить то, что я пытаюсь?

...