C++中类成员函数作为回调函数的几种方法
2014-02-23 22:11
603 查看
写了一个C++小游戏,想法是间接别人的C语言,但是真正自己操作起来,还是会遇到各种问题,同时也让自己更真切的学到了一些过眼即忘,只有亲自动手才能学到的知识。
如何实现C++中的成员作为回调函数?这是我遇到的最大的问题:
当你调用signal()时需要一个void(*)(int)的函数指针,当你调用pthread_create()时你需要一个(void *)(*)(void *)的函数指针,这时如果你需要使一个非静态成员函数作为回调函数的话,是不会被编译器同通过的。以上篇blog中的情景为例,成员函数moveSnake的函数指针类型真正为void(Snake::*)(),不是你想要的。这时可以:
1)如果这个函数是非静态成员函数,而且可以从类中提到类外,作为一个普通函数,这样就可以以正常的函数指针调用了。
2)如果这个函数是静态成员函数,那么不需要任何转换,因为静态成员函数不属于任何对象,它本身就是一个普通函数指针。
3)如果这个函数不操作任何非静态的数据成员,那么就可以加static使之变成静态成员函数,此例中由于moveSnake需要操作数据成员,所以这种方法此处不同。
4)通过一个友元函数,加一个间接层解决问题,具体参见blog.sina.com.cn/s/blog_4298002e0100euh8.html 。
5)通过boost::function和boost::bind,这个可以达到调用成员函数的目的,并不能解决此处的问题,因为最后function<void(int)>无法转换成void(*)(int)。具体可以参见stackoverflow.com/questions/3381829/how-do-i-implement-a-callback-in-c。
#include <signal.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class Fred {
public:
void memberFn(){
}
static void staticMemberFn(int x){} // A static member function can usually handle it
};
// Wrapper function uses a global to remember the object:
Fred object_which_will_handle_signal;
void Fred_memberFn_wrapper(int)
{
object_which_will_handle_signal.memberFn();
}
int main()
{
/* signal(SIGINT, Fred::memberFn); */ // Can NOT do this
signal(SIGALRM, Fred_memberFn_wrapper); // OK
signal(SIGINT, Fred::staticMemberFn); // OK usually; see below
}
普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。普通成员函数
属于类的对象,对象可以有许多个,这样编译器就不知到绑定到哪个地址了。而static成员函数属于类,只有一个实例,就可以作为普通函数指针使用。
[/code]
如何实现C++中的成员作为回调函数?这是我遇到的最大的问题:
当你调用signal()时需要一个void(*)(int)的函数指针,当你调用pthread_create()时你需要一个(void *)(*)(void *)的函数指针,这时如果你需要使一个非静态成员函数作为回调函数的话,是不会被编译器同通过的。以上篇blog中的情景为例,成员函数moveSnake的函数指针类型真正为void(Snake::*)(),不是你想要的。这时可以:
1)如果这个函数是非静态成员函数,而且可以从类中提到类外,作为一个普通函数,这样就可以以正常的函数指针调用了。
2)如果这个函数是静态成员函数,那么不需要任何转换,因为静态成员函数不属于任何对象,它本身就是一个普通函数指针。
3)如果这个函数不操作任何非静态的数据成员,那么就可以加static使之变成静态成员函数,此例中由于moveSnake需要操作数据成员,所以这种方法此处不同。
4)通过一个友元函数,加一个间接层解决问题,具体参见blog.sina.com.cn/s/blog_4298002e0100euh8.html 。
5)通过boost::function和boost::bind,这个可以达到调用成员函数的目的,并不能解决此处的问题,因为最后function<void(int)>无法转换成void(*)(int)。具体可以参见stackoverflow.com/questions/3381829/how-do-i-implement-a-callback-in-c。
boost::function<void()> callback; Target myTarget; callback=boost::bind(&Target::doSomething,&myTarget); callback(); // calls the function 6)通过强制转换 #include <pthread.h> #include <iostream> using namespace std; class MyClass { pthread_t tid; void func() { cout<<"强制转换"; } public: bool startThread() { typedef void* (*FUNC)(void*);//定义FUNC类型是一个指向函数的指针 FUNC callback = (FUNC)&MyClass::func;//强制转换func()的类型 int ret = pthread_create( &tid , NULL , callback , this ); if( ret != 0 ) return false; else return true; } }; int main() { MyClass myClass; myClass.startThread(); } 7)也是通过加一个间接层,包装真正的信号处理函数即可,即上一篇文中解决文题用到的方法。
#include <signal.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class Fred {
public:
void memberFn(){
}
static void staticMemberFn(int x){} // A static member function can usually handle it
};
// Wrapper function uses a global to remember the object:
Fred object_which_will_handle_signal;
void Fred_memberFn_wrapper(int)
{
object_which_will_handle_signal.memberFn();
}
int main()
{
/* signal(SIGINT, Fred::memberFn); */ // Can NOT do this
signal(SIGALRM, Fred_memberFn_wrapper); // OK
signal(SIGINT, Fred::staticMemberFn); // OK usually; see below
}
普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。普通成员函数
属于类的对象,对象可以有许多个,这样编译器就不知到绑定到哪个地址了。而static成员函数属于类,只有一个实例,就可以作为普通函数指针使用。
[/code]
相关文章推荐
- 关于指针的一些事情
- C/C++数据对齐详细解析
- C++中引用的使用总结
- C与C++之间相互调用实例方法讲解
- C++中引用(&)的用法与应用实例分析
- 解析C++ 浮点数的格式化输出
- 深入分析C++中几个最不常用的关键字
- c++中inline的用法分析
- 深入解析C++ Data Member内存布局
- 从汇编看c++中默认构造函数的使用分析
- 关于C++中的友元函数的一些总结
- C++的sstream标准库详细介绍
- 基于C++自动化编译工具的使用详解
- 浅谈C++中的string 类型占几个字节
- C/C++ 宏详细解析
- 深入分析C++中两个大数相乘结果不正确的问题
- 探讨C++中数组名与指针的用法比较分析
- 深入解析C++中的引用类型
- C++可变参数的实现方法
- C++中的常对象与常对象成员详解