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

今天写了一个类,类中用到了创建线程函数:_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}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章