假设线程入口函数和创建线程函数原型如下:
线程入口函数原型:
typedef void* (*FNTHREAD)(void *pParam);
其中:pParam传递给线程的参数。 并假定所有的函数、方法都编译成stdcall调用约定。
创建线程函数原型:
THREAD ThreadCreate(void *pParam, FNTHREAD fnThreadProc) ;
其中:pParam传递给线程的参数。fnThreadProc线程入口函数。THREAD函数返回类型,线程句柄。
不考虑等待线程结束、释放线程句柄...等问题。
一、全局函数作为线程的入口函数
void* FunThreadGlobal(void *pParam) ;
class CThreadGlobal
{
public:
THREAD ThreadRun()
{
return ThreadCreate(this, FunThreadGlobal) ;
}
void* ThreadProc()
{
cout<<"CThreadGlobal"<<endl ;
return NULL ;
}
};
void* FunThreadGlobal(void *pParam)
{
CThreadGlobal *p = static_cast<CThreadGlobal *>(pParam) ;
return (p != NULL) ? p->ThreadProc() : NULL ;
}
二、静态成员函数作为线程的入口函数
class CThreadStatic
{
public:
THREAD ThreadRun()
{
return ThreadCreate(this, FunThreadStatic) ;
}
void* ThreadProc()
{
cout<<"CThreadStatic"<<endl ;
return NULL ;
}
private:
static void* FunThreadStatic(void *pParam) ;
};
void* CThreadStatic::FunThreadStatic(void *pParam)
{
CThreadStatic *p = static_cast<CThreadStatic *>(pParam) ;
return (p != NULL) ? p->ThreadProc() : NULL ;
}
三、友元函数作为线程的入口函数
class CThreadFriend
{
public:
friend void* FunThreadFriend(void *pParam) ;
THREAD ThreadRun()
{
return ThreadCreate(this, FunThreadFriend) ;
}
void* ThreadProc()
{
cout<<"CThreadFriend"<<endl ;
return NULL ;
}
};
static void* FunThreadFriend(void *pParam)
{
CThreadFriend *p = static_cast<CThreadFriend *>(pParam) ;
return (p != NULL) ? p->ThreadProc() : NULL ;
}
四、无参成员函数作为线程的入口函数
类成员函数有个隐含的this指针,对于类成员函数ReturnType Class::MemFun(ParameterList...) ;
可以看成是ReturnType MemFun(Class * this, ParameterList...) ;
因此无参的成员函数刚好可以当线程的入口函数。但C++不支持将成员函数指针强制转换成其它类型的指针,
成员函数ReturnType Class::MemFun();直接强制类型转换 FNTHREAD fun = (FNTHREAD)&Class::MemFun; 这样写法将引起编译错误。
这种方式不行,那么就换别的。条条大道通罗马,能达到目的就行。下面介绍两种实现方式:
4.1、函数模板方式
template<typename T, typename F>
THREAD ThreadCreateTemplate(T *t, F f)
{
typedef void* (T::*THISCALLFUN)(); //指向类T的无参成员函数的指针类型
THISCALLFUN fnTcf = (THISCALLFUN)f; //这样fnTcf就保存了成员函数的地址
FNTHREAD fnFun = *(FNTHREAD*)&fnTcf ; //将fnTcf取地址以后,再取该地址的内容(成员函数的地址)
return ThreadCreate(t, fnFun) ; //t就当this指针,
}
class CThreadTemplate
{
public:
THREAD ThreadRun()
{
return ThreadCreateTemplate(this, &CThreadTemplate::ThreadProc) ;
}
void* ThreadProc()
{
cout<<"CThreadTemplate"<<endl ;
return NULL ;
}
};
4.2、变参函数方式
虽然不能将成员函数指针强制转换成其它类型的指针,但尝试发现可以把成员函数指针传给可变参数的函数。
THREAD ThreadCreateVarParam(void *pParam, ...)
{
FNTHREAD fnFun = NULL;
va_list pArgList ;
va_start (pArgList, pParam) ;
fnFun = *(FNTHREAD *)pArgList ;
va_end (pArgList) ;
return fnFun != NULL ? ThreadCreate(pParam, fnFun) : (THREAD)0 ;
}
class CThreadVarParam
{
public:
THREAD ThreadRun()
{
return ThreadCreateVarParam(this, &CThreadVarParam::ThreadProc) ;
}
void* ThreadProc()
{
cout<<"CThreadVarParam"<<endl ;
return NULL ;
}
};