很多时候我们在C++多线程开发时,都会或多或少遇到线程函数为C++类中的某个成员函数,此时可能会发生什么呢?你有可能会杂么做呢?
接下来我就为大家总结一下我在这方面走过的一个历程
1.问题一
记得我在之前在写一个udp传输文件的程序时,我就第一次遇到了线程函数为C++类的成员函数,当时遇到的问题,大概意思如下:
#include<iostream>
#include <thread>
#include <unistd.h>
class Test
{
public:
Test():testThread_(print)
{
}
void print(void)
{
std::cout<<"hello"<<std::endl;
}
private:
std::thread testThread_;
};
int main(int argc,char **argv)
{
Test test;
sleep(1000);
return 0;
}
如上述代码,当我编译时会产生如下编译结果
根据第一个error报错,貌似程序希望我们把print函数设为静态函数,第二个error则意思是我们传递的参数不能和std::thread所匹配。我的前几篇博文有写过std::thread相关的知识,它的第一个参数为函数指针,而我们的标准C++里这样是获取不到其成员函数的指针的所以才会产生上述的报错。关于C++获取其成员函数方面的知识,请参考这个链接http://www.zhihu.com/question/27738023
2.(一)解决方案
根据一种的报错,我想我们想到的最简单的方法就是把成员函数设成静态成员函数
具体如下
#include<iostream>
#include <thread>
#include <unistd.h>
class Test
{
public:
Test():testThread_(print)
{
}
static void print(void)
{
std::cout<<"hello"<<std::endl;
}
private:
std::thread testThread_;
};
int main(int argc,char **argv)
{
Test test;
sleep(1000);
return 0;
}
这个代码解决了我在一中遇到的问题
3.问题二
2中似乎表面上解决了我的问题,但事实上由于2的解决方案,我又遇到了新的问题
#include<iostream>
#include <thread>
#include <unistd.h>
class Test
{
public:
Test(int m):n(m),testThread_(print)
{
}
static void print(void)
{
std::cout<<n<<std::endl;
}
private:
int n;
std::thread testThread_;
};
int main(int argc,char **argv)
{
Test test(8);
sleep(1000);
return 0;
}
在上述代码中,当我的线程函数在使用类的成员函数时,编译时会报错
这是因为,我们的静态成员函数并不能使用非静态的成员变量(因为它没有某个具体对象的this指针)
4.(二)解决方案1
解决方案很简单,我们只需给静态成员函数传递某对象的this指针即可
具体如下
#include<iostream>
#include <thread>
#include <unistd.h>
class Test
{
public:
Test(int m):n(m),testThread_(print,this)
{
}
static void print(Test *pt)
{
std::cout<<pt->n<<std::endl;
}
private:
int n;
std::thread testThread_;
};
int main(int argc,char **argv)
{
Test test(8);
sleep(1000);
return 0;
}
5.(二)解决方案2
4中的确完全解决了我们在线程中调用类的成员函数的所有问题,但是你会不会感觉其用起来很别扭,本来我们只是向使一个成员函数为线程函数,这样我们就可以在该线程函数中直接使用该类的成员变量了,但是由于2中有叙述的那些原因,结果使我们不得不使用将成员函数设为静态的,结果就是我们现在使用类的成员变量会这么麻烦,感觉好不爽。难道就没什么方法可以让我们不是成员函数变为静态的?
哈哈,当然是有的具体方案如下
#include<iostream>
#include <thread>
#include <unistd.h>
#include <functional>
class Test
{
public:
Test(int m):n(m),testThread_(std::bind(&Test::print,this))
{
}
void print(void)
{
std::cout<<n<<std::endl;
}
private:
int n;
std::thread testThread_;
};
int main(int argc,char **argv)
{
Test test(8);
sleep(1000);
return 0;
}
我们可以像上述代码那样只需用C++11新标准的std::bind函数将其成员函数与对应的对象指针(即this指针)绑定之后便可高枕无忧的解决我们上述的所有问题了