当前位置: 技术问答>linux和unix
pthread线程库和C++一起使用的问题
来源: 互联网 发布时间:2015-07-11
本文导语: 最近在Linux下学习C++,在编一个程序时需要多线程支持。 我最初的想法是在一个类(比如CWinamp)中,提供一个方法(比如CWinamp.play()),当调用这个方法时,就会创建一个线程,去执行一个很费时的操作.但是在编写中却遇...
最近在Linux下学习C++,在编一个程序时需要多线程支持。
我最初的想法是在一个类(比如CWinamp)中,提供一个方法(比如CWinamp.play()),当调用这个方法时,就会创建一个线程,去执行一个很费时的操作.但是在编写中却遇到了一个问题。
在pthread库中,创建线程的函数pthread_create()需要一个(void*)(*func)(void*)类型的参数,但是当我将类的一个成员函数(比如void* CWinamp::dosomething(void *))传给它时,编译器却告诉我类型不匹配。
我想这是因为对于类成员函数,由于编译器要隐式的添加一个this指针作为参数,而导致的类型不匹配。
请问,对于这种问题,有什么好的解决办法么?或者,在LinuxUnix下,如何在C++程序中完美的使用多线程?
我最初的想法是在一个类(比如CWinamp)中,提供一个方法(比如CWinamp.play()),当调用这个方法时,就会创建一个线程,去执行一个很费时的操作.但是在编写中却遇到了一个问题。
在pthread库中,创建线程的函数pthread_create()需要一个(void*)(*func)(void*)类型的参数,但是当我将类的一个成员函数(比如void* CWinamp::dosomething(void *))传给它时,编译器却告诉我类型不匹配。
我想这是因为对于类成员函数,由于编译器要隐式的添加一个this指针作为参数,而导致的类型不匹配。
请问,对于这种问题,有什么好的解决办法么?或者,在LinuxUnix下,如何在C++程序中完美的使用多线程?
|
对于这种问题,我在Windows中使用pthread库时一般是这么实现的,由于Windows下的pthread库实际上用法与Linux中的完全一致,因此 应该可行。
用你的例子来说明,你可以这种做,再实现一个同名但参数不同的的静态函数,如
static int play(void *p);
实现很简单:
int CWinamp::play(void *p)
{
((CWinamp*)p)->play();
return 1;
}
然后,在pthread_create时,将这个CWinamp::play作为func型参数,同时将当前的CWinamp对象的地址传入作为参数(void *),如此即可。这样,就可以调用CWinamp中一切非Static型函数了。
用你的例子来说明,你可以这种做,再实现一个同名但参数不同的的静态函数,如
static int play(void *p);
实现很简单:
int CWinamp::play(void *p)
{
((CWinamp*)p)->play();
return 1;
}
然后,在pthread_create时,将这个CWinamp::play作为func型参数,同时将当前的CWinamp对象的地址传入作为参数(void *),如此即可。这样,就可以调用CWinamp中一切非Static型函数了。
|
可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。通过查询资料发现,其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的作用,使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性,适合于任何C++。
1). 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。
2). 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。
1). 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。
2). 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。
|
把这个成员函数定义成static函数才行。
要么就做成普通函数。
要么就做成普通函数。