如何定义通用成员函数指针

发布于 2024-08-19 12:16:11 字数 347 浏览 4 评论 0原文

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

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

谢谢伙伴们。

编辑:这段代码必须在 Windows 和实时操作系统(VxWorks)上运行,所以不使用外部库会很好

。我需要的是一个 Timer 类,它在没有参数的“AnyClass.AnyMethod”构造函数中接受一个参数并返回 void 我必须存储这个参数,而后者在代码的某个点只需执行该变量指向的方法。希望是明确的。

I have created a Timer class that must call a callback method when the timer has expired. Currently I have it working with normal function pointers (they are declared as void (*)(void), when the Elapsed event happens the function pointer is called.

Is possible to do the same thing with a member function that has also the signature void (AnyClass::*)(void)?

Thanks mates.

EDIT: This code has to work on Windows and also on a real-time OS (VxWorks) so not using external libraries would be great.

EDIT2: Just to be sure, what I need is to have a Timer class that take an argument at the Constructor of tipe "AnyClass.AnyMethod" without arguments and returning void. I have to store this argument and latter in a point of the code just execute the method pointed by this variable. Hope is clear.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情徒 2024-08-26 12:16:12

依赖关系,依赖关系...是的,boost 确实很好,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();

Dependencies, dependencies... yeah, sure boost is nice, so is mem_fn, but you don't need them. However, the syntax of calling member functions is evil, so a little template magic helps:

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

Now you can just use Callback as a callback storing mechanism so:

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

And

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

(*callback)();
// or...
callback->call();
梦过后 2024-08-26 12:16:12

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

The best solution I have used for that same purpose was boost::signal or boost::function libraries (depending on whether you want a single callback or many of them), and boost::bind to actually register the callbacks.

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
}
无法言说的痛 2024-08-26 12:16:12

也许标准的 mem_fun 已经足够满足您的需求了。它是STL的一部分。

Maybe the standard mem_fun is already good enough for what you want. It's part of STL.

淡紫姑娘! 2024-08-26 12:16:12

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

boost::function looks like a perfect fit here.

百合的盛世恋 2024-08-26 12:16:12

我假设有一个这样的界面:

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 you 回调升级为使用 boost::function 或自制版本(如 Kornel 的答案)。然而这需要真正的 C++ 开发人员参与,否则很可能会引入 bug。

我的解决方案的优点是它只是一个模板函数。并不是所有事情都会出错。我的解决方案的一个缺点是它可能会通过强制转换为 void* 并返回来分割您的类。请注意,只有 AnyClass* 指针作为 void* 传递到回调注册。

I'm assuming an interface like this:

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

I think a better solution would be to upgrade call you callback to either use boost::function or a homegrown version (like Kornel's answer). However this require real C++ developers to get involved, otherwise you are very likely to introduce bugs.

The advantage of my solution is that it is just one template function. Not a whole lot can go wrong. One disadvantage of my solution is it may slice your class with cast to void* and back. Be careful that only AnyClass* pointers are passes as void* to the callback registration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文