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

遇到的问题

我们在编程中需要把数据封装成一个类,调用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++模板

//声明定义一个模板函数

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++教

时间: 2024-11-03 05:42:46

成员函数作为线程函数调用的相关文章

类的成员函数实现线程的回调函数

一般都是用静态函数作为线程的回调函数实现,但是总是感觉不是很顺畅,更改吧,就好像破坏了类的封装性,不改吧,访问实在是麻烦.所以,今天要做的就是让类的成员函数作为线程的回调函数存在,其中使用的一个比较特殊的结构就是 union { void ( *ThreadProc)(LPVOID pvParam); void ( student::*MemberProc)(LPVOID pvParam); } Proc; 联合类,用于转换类成员方法指针到普通函数指针 下面是一个小李子,变量名 就凑活看吧,核心

并发编程: c++11 thread(Func, Args...)利用类成员函数创建线程

c++11是VS2012后支持的新标准,为并发编程提供了方便的std::thread. 使用示例: #include <thread> void thread_func(int arg1, int arg2, float* arg3){ arg3 = (arg1*1.0)/(arg1 + arg2); cout << "arg1 / (arg1 + arg2) = " << arg3 << endl; return; } void mai

在C++的类中,普通成员函数不能作为pthread_create的线程函数,如果要作为pthread_create中的线程函数,必须是static

在C++的类中,普通成员函数不能作为pthread_create的线程函数,如果要作为pthread_create中的线程函数,必须是static ! 在C语言中,我们使用pthread_create创建线程,线程函数是一个全局函数,所以在C++中,创建线程时,也应该使用一个全局函数.static定义的类的成员函数就是一个全局函数. 更多 参考  http://blog.csdn.net/ksn13/article/details/40538083 #include <pthread.h> #

C++ 11 线程调用类的成员函数解决办法

在C++中,_beginthreadex 创建线程是很麻烦的.要求入口函数必须是类的静态函数. 通常,可以采用thunk,或者模板来实现. 因C++ 11中引入了 std::async ,可以很好的解决这个问题了. 值得注意的是,在循环中 std::async 创建线程,我试了好多次总是失败,后来看老外的代码,采用 std::move解决了问题. 具体见实现代码. // ConsoleApplication1.cpp : 定义控制台应用程序的入口点. #include "stdafx.h&quo

MFC——4个基本类中的成员函数介绍

09121852 杜军 机械设计及理论 1. CMainFrame ActivateFrame使框架对用户可视并可用 CalcWindowRect每当主框架窗口的客户区尺寸发生变化或控制条的位置发生变化,需 要重新排列客户区时,调用该函数 Create调用以构造和初始化一个与CFrameWnd对象有关的Windows框架窗口 DefWindowProc该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理 DestroyWindow销毁指定的窗口 DoDataExchange 

C++中类成员函数作为回调函数

注:与tr1::function对象结合使用,能获得更好的效果,详情见http://blog.csdn.net/this_capslock/article/details/38564719 回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过. 普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从

类的成员函数指针(比較深入)

From:http://blog.csdn.net/hairetz/archive/2009/05/06/4153252.aspx 个人感觉对于类的成员函数指针这块解说的比較深入具体 推荐阅读 ///////////////////////////////////////////////// 先看这样一段代码 class test {    public:       test(int i){ m_i=i;}       test(){} void hello()       {        

C++学习笔记(2)---2.5 C++函数编译原理和成员函数的实现

转载自:http://c.biancheng.NET/cpp/biancheng/view/2996.html点击打开链接 从上节的例子可以看出,对象的内存模型中只保留了成员变量,除此之外没有任何其他信息,程序运行时不知道 obj 的类型为 Demo,也不知道它还有一个成员函数 display().那么,究竟是如何通过对象调用成员函数的呢? C++函数的编译 C++和C语言的编译方式不同.C语言中的函数在编译时名字不变,或者只是简单的加一个下划线_(不同的编译器有不同的实现),例如,func()

C++成员函数指针错误用法警示(成员函数指针与高性能的C++委托,三篇),附好多评论

今天做一个成绩管理系统的并发引擎,用Qt做的,仿照QtConcurrent搞了个模板基类.这里为了隐藏细节,隔离变化,把并发的东西全部包含在模板基类中.子类只需注册需要并发执行的入口函数即可在单独线程中执行.最终目标是,继承的业务逻辑类外部调用时有两个接口可选,调用syncRun同步执行:调用由引擎自动生成的asyncRun就异步执行.最终自动生成asyncRun的模板基类没能实现,主要原因是mingw对this处理的太有问题了!!原本以为编译器问题,后来才知道成员函数指针和this指针如此特殊