参考:http://blog.csdn.net/braveyly/article/details/3446472
对于”在类里面的成员函数创建线程怎么搞“都有两三个月的疑问了,一直没想到什么好的方法。对于创建线程的调用函数归属问题不太清楚,也没什么时间做个实验。
下面的实验借鉴链接中的博客的思想,实验环境为ubuntu 11.04, Emacs。
补充:
Linux下,创建线程为:pthread_create(); 回调函数的形式为:void * thread_proc(void * arg);
Windows下,创建线程为:CreateThread(); 回调函数形式为:DWORD WINAPI thread_proc(LPVOID lpParam);
一共有三种方法:
1. 这种情况,一般是将线程函数申明为静态成员变量,写入口函数时,指明该入口函数所在的类
在类中定义的成员函数,VC在编译时会强加一个this指针,通过函数名无法定位该入口函数。将该成员函数声明为static类型,可以将this指针除去。
缺点:static成员函数只能访问static成员。
在类A的成员函数中创建线程,代码如下:
pthread_t threadID;
int err=pthread_create(&threadID, NULL, A::thread_proc, NULL);
声明时:
class A
{
static void * thread_proc(void * arg);
};
注意:入口函数的输出类型和输入类型不能变化。
注意:友元函数在头文件中声明,在cpp文件中定义。如果直接定义在头文件中,链接的时候会有多重定义错误提示。
3. 可以对成员函数实现回调,并访问非静态成员的。
这种方法充分利用了传给回调函数的指针,将类中的成员打包发送给了回调函数,从而实现访问。
(下面没有进行试验,部分需要改动)
如下所示,这是为了实现线程函数访问类成员而实现的类。比MFC的实现方法好象要好一点。
class base; //? typedef int (base::*fnCallBack)(void *p); //用来封装回调类的信息 struct callback { void *param; fnCallBack *pfuc; base *pThis; //存放类的信息 }; class base { //回调函数,没有试验,但应该按照回调函数的标准来定义 static int myThreadfuc(void * p) { struct callback *p1=(struct callback *)p; //将封装后的信息解包 base * pthis=p1->base; fnCallBack *pfuc=p1->pfuc; void * param=p1->param; //运行实际要运行的函数 int i=(pthis->*pfuc)(param); delete p; return i; } public: void myCreateThread(fnCallBack pfuc,void *param) { struct callback *p=new struct callback; //把封装后的类的成员以及回调函数打包 p.param=param; //客户要传给实际要运行函数的参数 p.pThis=this; //保存类的指针 p.pfuc=pfuc; //保存实际要运行的函数 //创建线程,注意其他参数自己补全 ::CreateThread(myThreadfuc,p); } virtual int myCallBack(void *p) { printf("It's base class./n"); return 0; } }; class derived:public base { int myCallBack(void *p) { printf("It's derived class/n"); } }; void myCreateThreadImitate(fnCallBack fuc,void *p) { (*fuc)(p); } void main() { base p; char *param; p.myCreateThread(&(base::myCallBack),param); derived p2; p2.myCreateThread(&(base::myCallBack),param); }