c++ 类成员函数 作回调函数

来源:互联网 发布:高达00 知乎 编辑:程序博客网 时间:2024/06/01 08:27

今天写了一个类,类中用到了创建线程函数:_beginthreadex()  (windows下的创建线程函数,这其实是一个C标准的线程函数,但跟windows联系紧密,只要是为解决Create_Thread()函数创建的线程如果调用了C函数库,就会发生内存泄露,所以这是个安全的函数,建议用这个。)  以下是一个成员函数的某段代码:

HANDLE   hth;
unsigned  uiThread1ID;hth = (HANDLE)_beginthreadex( NULL,         // security                                   0,            // stack size                                   NetRawThreadProc,                                   this,           // arg list                                   0,  // so we can later call ResumeThread()                                   &uiThread1ID );CloseHandle(hth);

功能就是创建一个线程,然后线程去执行NetRawThreadProc(),这个NetRawThreadProc 也是一个类成员函数,它的原型为:


void*  NetWorkThread::NetRawThreadProc (void* pParam){//blablabla~~~}

然后编译一下,傻眼了,说该成员函数与回调类型不匹配噢,MLGB!

我从头到尾都是参照标准的方法,来调用回调函数啊(因为还不知道this指针这个鬼~)

所以我的解决思路是:

1. 回调类型不匹配,我就先check 我的NetRawThreadProc() 的返回值类型、参数类型,发现没有错;

2.是否_beginthreadex()的第三个参数给错了,然后查到这第三个参数,有两种使用方式,一种是在调用的函数名前面加 & ,一种是不加:

函数名,本来就是函数地址,这时候再加个 & 也是一样,地址不会发生改变,所以还是能够调用;

3.可能是NetWorkThread::有问题:

try了一下,把NetWrokThread:: 去掉后再来调用,就一切正常。

找到问题了,成员函数作为回调函数,会出问题。

解决方法一:

用普通函数来做中间层:

void* func(void*)

普通函数为上述格式,然后利用回调函数的特性,传递 this 指针到第四个参数,然后func()就可以使用this指针来调用类成员函数了,相当折中。

但我不喜欢这个方式,因为这样封装性就破坏了。


这个时候有第二种解决方法:使用static 成员函数作为回调函数,然后在static中调用成员函数;


void* NetWorkThread::NetRawThreadProc (void* pParam){NetThreadProc();}

此时编译报错,提示NetThreadProc也需要是静态成员;我在这里调用成员函数,而不是直接用static成员函数来进行操作,是因为static要操作的类成员变量必须是static的,这样我就需要把成员变量该为static了。所以必须要用某种方法来调用成员函数。

我们可以利用回调函数传递this指针,迂回解决这个问题:

void* NetWorkThread::NetRawThreadProc (void* pParam){NetWorkThread *netObject = (NetWorkThread*)pParam;netObject->NetThreadProc();}

这样,类成员函数就能正确调用了,整体格式为:


HANDLE   hth;
unsigned  uiThread1ID;hth = (HANDLE)_beginthreadex( NULL,         // security                                   0,            // stack size                                   NetRawThreadProc,                                   this,           // arg list                                   0,  // so we can later call ResumeThread()                                   &uiThread1ID );CloseHandle(hth);

void* NetWorkThread::NetRawThreadProc (void* pParam){NetWorkThread *netObject = (NetWorkThread*)pParam;netObject->NetThreadProc();}

void NetWorkThread::NetThreadProc(){//blablalbla}


0 0
原创粉丝点击