如何定义一般成员函数指针

时间:2010-01-27 14:44:57

标签: c++ function-pointers member-function-pointers

我创建了一个Timer类,当计时器到期时必须调用一个回调方法。目前我使用普通函数指针(它们被声明为void(*)(void),当Elapsed事件发生时,调用函数指针。

是否可以使用也具有签名void(AnyClass :: *)(void)的成员函数执行相同的操作?

感谢队友。

编辑:此代码必须在Windows上以及在实时操作系统(VxWorks)上运行,因此不使用外部库会很棒。

EDIT2:只是为了确定,我需要的是有一个Timer类,它在构造函数中使用t参与“AnyClass.AnyMethod”而不带参数并返回void。我必须存储这个参数,后者在代码中只执行此变量指向的方法。希望很清楚。

5 个答案:

答案 0 :(得分:8)

依赖关系,依赖关系......是的,确定提升很好,mem_fn也是如此,但你不需要它们。但是,调用成员函数的语法是邪恶的,所以一点模板魔术有助于:

   class Callback
   {
   public:
      void operator()() { call(); };
      virtual void call() = 0;
   };

   class BasicCallback : public Callback
   {
      // pointer to member function
      void (*function)(void);
   public:
      BasicCallback(void(*_function)(void))
          : function( _function ) { };
      virtual void call()
      { 
          (*function)();
      };
   };   

   template <class AnyClass> 
   class ClassCallback : public Callback
   {
      // pointer to member function
      void (AnyClass::*function)(void);
      // pointer to object
      AnyClass* object;        
   public:
      ClassCallback(AnyClass* _object, void(AnyClass::*_function)(void))
          : object( _object ), function( _function ) { };
      virtual void call()
      { 
          (*object.*function)();
      };
   };

现在你可以使用Callback作为回调存储机制,所以:

void set_callback( Callback* callback );
set_callback( new ClassCallback<MyClass>( my_class, &MyClass::timer ) );

Callback* callback = new ClassCallback<MyClass>( my_class, &MyClass::timer ) );

(*callback)();
// or...
callback->call();

答案 1 :(得分:4)

我用于同一目的的最佳解决方案是boost::signalboost::function个库(取决于您是想要单个回调还是其中许多回调),并且boost::bind实际注册回调。

class X {
public:
   void callback() {}
   void with_parameter( std::string const & x ) {}
};
int main()
{
   X x1, x2;
   boost::function< void () > callback1;

   callback1 = boost::bind( &X::callback, &x1 );
   callback1(); // will call x1.callback()

   boost::signal< void () > multiple_callbacks;
   multiple_callbacks.connect( boost::bind( &X::callback, &x1 ) );
   multiple_callbacks.connect( boost::bind( &X::callback, &x2 ) );
   // even inject parameters:
   multiple_callbacks.connect( boost::bind( &X::with_parameter, &x1, "Hi" ) );

   multiple_callbacks(); // will call x1.callback(), x2.callback and x1.with_parameter("Hi") in turn
}

答案 2 :(得分:2)

也许标准mem_fun已经足够你想要的了。它是STL的一部分。

答案 3 :(得分:1)

boost::function看起来非常适合。

答案 4 :(得分:0)

我假设这样的界面:

void Timer::register_callback( void(*callback)(void*user_data), void* user_data );

template<typename AnyClass, (AnyClass::*Func_Value)(void)>
void wrap_method_callback( void* class_pointer )
{
   AnyClass*const self = reinterpret_cast<AnyClass*>(class_pointer);
   (self->*Func_Value)();
}

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

int main ()
{
   Timer t;
   A a = { 10 };
   t.register_callback( &wrap_method_callback<A,&A::callback>, &a );
}

我认为更好的解决方案是升级调用你回调到使用boost :: function或自己开发的版本(如Kornel的回答)。然而,这需要真正的C ++开发人员参与其中,否则你很可能会引入错误。

我的解决方案的优点是它只是一个模板功能。不是很多都可能出错。我的解决方案的一个缺点是它可能会使用强制转换为void*并将其分类。请注意,只有AnyClass*个指针作为void*传递给回调注册。