C++线程入口函数的几种方式

本文详细解析了如何使用全局函数、静态成员函数、友元函数以及无参成员函数作为线程的入口函数,并通过函数模板和变参函数的方式解决了成员函数无法强制转换为其他类型指针的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设线程入口函数和创建线程函数原型如下:

线程入口函数原型:
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 ;
	}
};



转载于:https://my.oschina.net/osbin/blog/215125

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值