类成员函数作为线程函数使用
类成员函数作为线程函数使用
C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象。函数体可以通过显示调用该指针或直接访问类内成员。
回调函数是用指针来调用的函数,最常使用的回调函数就是在创建线程时,以一个函数指针以及传递给这个函数多个参数来调用线程函数来创建线程。那么一般的类成员函数是不能用作回调函数的,因为库函数在使用回调函数时,都会传递指定的符合回调函数声明的的参数给回调函数,而类成员函数隐式包含一个this指针参数,所以把类成员函数当作回调函数编译时因为参数不匹配会出错。
如果类内成员函数调用回调函数怎么实现呢?一般有两种方法:
1.回调函数声明在类外,全局的传类对象指针给回调函数即可使用类内成员,因为回调函数是全局的所以影响了类的封装性
2.类内成员函数作为回调函数
利用关键名static声明类内成员函数,因为类静态成员函数只能操作类静态成员,所以函数若想访问类成员,只能通过调用函数传递类对象指针给回调函数,或者在类内声明一个静态指针,该指针指向类,然后在函数中调用该指针访问类成员。
但是上面两种方法的使用还是线程并不属于对象,还是属于类。
我这里要说的是将一个类的成员函数作为线程函数使用,并不是以上面两种。
因为一般都是用静态函数作为线程的回调函数实现,但是有时候总是感觉不是很顺畅,更改,就好像破坏了类的封装性,不改,访问实在是麻烦。所以,今天要做的就是让类的成员函数作为线程的回调函数存在,其中使用的一个比较特殊的结构就是
union
{
void (*ThreadProc)(LPVOID pvParam);
void (student::*MemberProc)(LPVOID pvParam);
} Proc;
联合类,用于转换类成员方法指针到普通函数指针。
方法1、下面看实例:下面例子中用printInfo作为线程回调函数
//ThreadMember.cpp : 定义控制台应用程序的入口点。
#include"stdafx.h"
#include<string>
#include<Windows.h>
#include<iostream>
using namespacestd;
class student
{
public:
student()
{
m_handle = NULL;
name = "Member fun is ThreadFun.";
age = 13;
}
void printInfo(LPVOID pvParam); //作为线程回调函数
void startUp();
private:
HANDLE m_handle;
int age;
string name;
};
union //用于转换类成员方法指针到普通函数指针(地址相同)
{
void ( *ThreadProc)(LPVOID pvParam);
void (student::*MemberProc)(LPVOID pvParam);
} Proc;
void student::printInfo(LPVOID pvParam)
{
student * pS = (student * )pvParam;
while( WaitForSingleObject(pS->m_handle,30000) != WAIT_OBJECT_0 ) //线程每隔一时间执行,如果要唤醒就加一个事件,改变信号状态
{
cout<< "age" <<"" <<pS->age<< endl;
cout<< "name" <<" " <<pS->name<< endl;
Sleep(2000);
}
}
voidstudent::startUp()
{
Proc.MemberProc =&student::printInfo;//指向成员函数
m_handle = CreateThread(NULL,0,LPTHREAD_START_ROUTINE(Proc.ThreadProc),this,0,0);
// ThreadProc和MemberProc在共联体类中,所以也间接指向成员函数
}
int _tmain(intargc, _TCHAR* argv[])
{
student s1;
s1.startUp();
system("pause");
_CrtDumpMemoryLeaks();
return 0;
}
方法2、通过友元函数实现。
//ThreadMember.cpp : 定义控制台应用程序的入口点。
#include"stdafx.h"
#include<string>
#include<Windows.h>
#include<iostream>
using namespace std;
class student
{
public:
student()
{
m_handle = NULL;
name = "Member fun is ThreadFun.";
age = 13;
}
friend UINT WINAPIprintInfo(LPVOID pvParam);
void startUp();
private:
HANDLE m_handle;
int age;
string name;
};
UINT WINAPI printInfo (LPVOID pvParam)
{
student * pS = (student * ) pvParam;
while(true ){
cout <<"age"<<pS-> age<<endl ;
cout <<"name"<<pS->name <<endl;
Sleep (2000);
}
return 0 ;
}
void student::startUp()
{
m_handle =CreateThread(NULL,0,LPTHREAD_START_ROUTINE(printInfo),this,0,0);
}
int _tmain(int argc, _TCHAR*argv[])
{
student s1;
s1.startUp();
system("pause");
_CrtDumpMemoryLeaks();
return 0;
}
以上两种方法可以讲一个类的成员函数作为线程函数去执行, 从而让对象维护线程。
且要做到线程同步,要创建一个自动重置类型的时间对象。如果是人工重置事件对象,当一个线程等待到一个人工重置的事件对象后这个事件对象任然处于有信号状态,所以其他线程也可以得到该事件对象。
类成员函数作为线程函数使用相关推荐
- 在别的函数或者线程函数里使用 PostMessage
在别的函数或者线程函数里使用 PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)小收获 分类: VC++ 2011-12-15 20 ...
- c++ 线程函数(类成员函数作为线程函数使用)
C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象.函数体可以通过显示调用该指针或直接访问类内成员. 回调函数是通过指针调用的函数,最常使用的回调函数就是在创建线 ...
- 第三节 线程传参详解、detach()大坑、成员函数做线程函数
1.传递临时对象作为线程参数 原始的输入程序如下: #include <iostream> #include <thread>using namespace std;void ...
- GetDlgItem、EnableWindow等函数在线程函数中无法使用
将窗口指针传递给线程,或者申明一个全局窗口指针,使线程内可见. 例如: UINT TestThread(LPVOID pParam) {CMyDlg* pDlg = (CMyDlg*)pParam;p ...
- 静态成员函数运用在CALLBACK函数和线程函数中《转载》
CALLBACK函数要声明称 static或全局,而在静态的函数中药调用非静态成员还不能调用,必须把这些成员也设置成静态的,不怎么方便,有好的解决方法吗. 其原因是把CALLBACK函数封装成C++类 ...
- linux线程创建 类函数吗,linux多线程创建时使用类成员函数作为参数
实际上所有线程都是用来处理C函数的,而不是C++类成员函数.标准库中提供一个API函数,这个函数以回调函数指针作为线程的执行代码并在单独的线程中调用回调函数.问题是在这样的线程库中不能创建执行对象成员 ...
- c++ 多线程 类成员函数_多线程(C++/Python)
多线程(C++/Python) 本文包括一下内容: 通过C++11的标准库进行多线程编程,包括线程的创建/退出,线程管理,线程之间的通信和资源管理,以及最常见的互斥锁,另外对python下多线程的实现 ...
- mfc 创建线程函数AfxBeginThread,线程中访问mfc控件
转字http://blog.csdn.net/guomsh/article/details/10377993 1. C++ 中如何定义线程函数 有两种方法:a. 定义线程函数为全局函数 b. 定 ...
- C++11线程函数类型错误
使用C++11的线程库写程序的时候,使用类的成员函数作为线程函数,类成员函数形式大概如下: class A { public: void foo() { cout << "foo ...
- c语言createthread函数,C++中CreateThread函数创建线程的用法和实例
CreateThread是一种微软在Windows API中提供了建立新的线程的函数,该函数在主线程的基础上创建一个新线程.线程终止运行后,线程对象仍然在系统中,必须通过CloseHandle函数来关 ...
最新文章
- 包装类接受string 会自动将数字类型string转换成对应得包装类型
- 2019版中国数字经济发展与就业白皮书
- python2和3的编码区别_Python2和3字符编码的区别
- html table没有align,HTML
- 浅析Kerberos原理,及其应用和管理
- 互联网架构:常用基础中间件介绍
- 浅析Unity 坐标系
- mysql.proc_升级后直接更改mysql.proc表
- 用ssh从ubuntu系统向ubuntu系统服务器发送文件
- jira状态评审未通过后 不能修改_去年职称申报未通过,今年再报名的,这些变化需要注意了...
- Skype for Business 2015全新部署_07.前端安装02
- zabbix 3.2 mysql_zabbix3.2的server和zabbix-agent2.2怎么监控MySQL的办法
- 清华计算机科学技术复试2018,2018清华大学计算机科学与技术系考研复试名单
- 网络邻居无法查找计算机,局域网中无法找到网上邻居的原因
- Java算法:牛客网哔哩哔哩bilibili笔试真题算法Java版1-14题
- 计算机中丢失 msvcr110.dll 怎么办
- C++刷题知识点总结2
- 数据库连接池之自定义连接池(mysql)
- Java媒体框架(JMF)资料
- 隐藏滚动条css3实现滚动同时隐藏滚动条
热门文章
- co作为前缀的意思_co前缀是什么意思
- Android 最常用的设计模式八 安卓源码分析—工厂方法模式factory
- 2018年大数据趋势 :人工智能… 数据分析将包含可视化模型…
- 电力英语计算机C级多少分,中级工程师英语加权分多少
- 电路中的输入输出阻抗以及阻抗匹配
- python 判断素数
- Mac 右键展示Copy path
- [MUI框架]-滑动侧边栏-webview模式
- linux esp分区,win10esp分区多大合适
- 拼音四线三格图片_一年级语文必考拼音拼读+书写规则,孩子开学就会用到!...