首页 文章

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

提问于
浏览
9

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

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

谢谢你的队友 .

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

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

5 回答

  • 1

    依赖关系,依赖关系...是的,确定提升很好,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();
    
  • 8

    我用于同一目的的最佳解决方案是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

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

  • 0

    boost::function看起来非常适合这里 .

  • 4

    我假设这样的界面:

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

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

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

相关问题