您的位置:首页 > 其它

成员函数作为线程函数调用

2014-09-14 16:53 218 查看

遇到的问题

我们在编程中需要把数据封装成一个类,调用pthread_create 利用成员函数去创建一个线程往往是不成功的!

error: argumentof type ‘void* (Threadpool::)(void*)’ does not match ‘void* (*)(void*)’

出现类型不匹配的问题。因为pthread_create需要的参数类型为void*(*)(void*),而thread_rounter作为类的成员函数时其类型是void* (Threadpool::)(void*)的成员函数指针。我们知道类的成员函数在经过编译器处理之后,会变成带有this指针参数的全局函数,所以类型注定是不会匹配的。

解决方案

天无绝人之路,尤其是对于C++这种被称为Wenger巨人刀(http://coolshell.cn/articles/6639.html#more-6639)的超级语言一定会有各种奇淫技巧提供出超乎想象的解决方案的。



各种编程语言的调侃图

声明static 成员函数作为线程函数

但是如果将thread_rounter声明为static类型,那么编译器会将static形式的函数,转换成不带this指针的全局函数,所以其类型可以与pthread_create需要的参数类型相匹配。但是类的静态成员函数无法访问类的非静态成员,不过这可以通过传递this指针解决这个问题。

staticvoid*threadfun(void*)

{

//dosomething

}

通过全局函数回调成员函数

void *thread (void *tmp)/线程执行函数

{

ClassName*p=( ClassName *)tmp;

//通过p指针间接访问类的非静态成员

}

终极解决方案C++模板

以下摘自(http://hi.baidu.com/angelevil2006/item/e1806ec30574ff11515058d1)
//声明定义一个模板函数

template <typename TYPE, void(TYPE::*_RunThread)() >

void* _thread_t(void* param)

{

TYPE* This = (TYPE*)param;

This->_RunThread();

return NULL;

}

/*

_thread_t:为模板函数名,可随意起

TYPE:类名

_ RunThread:为TYPE类中成员函数的名称,在这里必须是pbulic 。不可以任意取名。返回类型和参数必须和类中的一致。

*/

class MyClass

{

public:

MyClass();

void _RunThread();

private:

pthread_t tid;

};

void MyClass::_RunThread()

{

this->DoSomeThing();

//...

}

MyClass::MyClass()

{

//利用C++强大的模板功能巧妙滴实现了函数转换

pthread_create(&tid, NULL, _thread_t<MyClass,&MyClass::_RunThread>, this);

}

函数模版不单可以替换类型本身,还能替换类型的成员函数。

注意:1、名称只能是_RunThread,不能在指定模版参数的时候修改;

2、_RunThread只能是public的,除非把_thread_t定义到MyClass的内部。

总结

这些奇淫技巧没有必要记住,用的时候能想起来查的到即可。以上说做的工作就只有一个目的,把函数类型转换成 void*(*)(void*)类型的。同理可以把这种技巧移植到其他的需要的地方,比如可以把成员函数转换成 T(*)(T*)的函数,这里就不一一解释了。

如果读者看到这里没有明白以上所说的是什么意思或者有点晕,没有关系,照猫画虎用就可以了。建议读者从新阅读C++教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: