3

メソッドを関数コールバックにバインドする必要がありますが、 demote-boostfunction-to-a-plain-function-pointer で説明されているように、このスニペットは合法ではありません。

この動作を取得する最も簡単な方法は何ですか?

struct C {
void m(int x) {
    (void) x;
    _asm int 3;
}};

typedef void (*cb_t)(int);
int main() {
    C c;
    boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1);
    cb_t raw_cb = *cb.target<cb_t>(); //null dereference
    raw_cb(1);
    return 0;
}
4

4 に答える 4

2

ブーストバインド関数と同じことを行うために、独自のクラスを作成できます。クラスがしなければならないのは、関数型と関数を含むオブジェクトへのポインタを受け入れることだけです。たとえば、これはvoidreturnおよびvoidparamデリゲートです。

template<typename owner>
class VoidDelegate : public IDelegate
{
public:
   VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
   {
      mFunction = aFunc;
      mOwner = aOwner;
   }
   ~VoidDelegate(void)
   {}
   void Invoke(void)
   {
      if(mFunction != 0)
      {
         (mOwner->*mFunction)();
      }
   }

private:
   void (owner::*mFunction)(void);
   owner* mOwner;
};

使用法:

class C
{
   void CallMe(void)
   {
      std::cout << "called";
   }
};
int main(int aArgc, char** aArgv)
{
   C c;
   VoidDelegate<C> delegate(&C::CallMe, &c);
   delegate.Invoke();
}

さて、VoidDelegate<C>は型なので、これらのコレクションを持つことは実用的ではないかもしれません。なぜなら、リストにクラスBの関数も含まれているとしたらどうでしょうか。できませんでした。

ここでポリモーフィズムが作用します。以下を呼び出す機能を持つインタフェースIDelegateを登録することができます。

class IDelegate
{
   virtual ~IDelegate(void) { }
   virtual void Invoke(void) = 0;
}

IDelegateを実装する場合VoidDelegate<T>は、IDelegateのコレクションを使用できるため、さまざまなクラスタイプのメソッドへのコールバックを使用できます。

于 2009-02-05T16:02:14.957 に答える
1
#include <iostream>
typedef void(*callback_t)(int);

template< typename Class, void (Class::*Method_Pointer)(void) >
void wrapper( int class_pointer )
{
   Class * const self = (Class*)(void*)class_pointer;
   (self->*Method_Pointer)();
}

class A
{
public:
   int m_i;
   void callback( )
   { std::cout << "callback: " << m_i << std::endl; }
};

int main()
{
   A a = { 10 };
   callback_t cb = &wrapper<A,&A::callback>;
   cb( (int)(void*)&a);
}
于 2010-01-27T17:31:59.027 に答える