linux线程创建 类函数吗,linux多线程创建时使用类成员函数作为参数
實(shí)際上所有線程都是用來(lái)處理C函數(shù)的,而不是C++類(lèi)成員函數(shù)。標(biāo)準(zhǔn)庫(kù)中提供一個(gè)API函數(shù),這個(gè)函數(shù)以回調(diào)函數(shù)指針作為線程的執(zhí)行代碼并在單獨(dú)的線程中調(diào)用回調(diào)函數(shù)。問(wèn)題是在這樣的線程庫(kù)中不能創(chuàng)建執(zhí)行對(duì)象成員函數(shù)的線程;只能使用普通的函數(shù)。因此,下列代碼是失敗的:
#include "class1.h"
int func (void *param )
{
pthread_t ptid;
// 下列調(diào)用導(dǎo)致編譯器錯(cuò)誤: "Cannot convert ''void (class1::*)()'' to ''void (*)()''"
// 意思是不能轉(zhuǎn)換類(lèi)型
return pthread_create ( &ptid, NULL, &class1::some_method, NULL);
}
上面的代碼之所以編譯失敗是因?yàn)閭鬟f到pthread_create()的第一個(gè)參數(shù)是類(lèi)class1的成員函數(shù)指針,而不是普通函數(shù)指針。從概念上講,普通函數(shù)和類(lèi)成員函數(shù)是兩個(gè)完全不同的事情。即使進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換也不行。那么如何解決這個(gè)問(wèn)題呢?
方法一:使用靜態(tài)成員函數(shù)
第一個(gè)解決方法是使回調(diào)成員函數(shù)為靜態(tài)。因?yàn)殪o態(tài)成員函數(shù)不帶隱含式參數(shù)“this”。因此,可以將其參數(shù)中的地址當(dāng)作是普通函數(shù)的指針來(lái)使用。如果要從靜態(tài)成員函數(shù)中訪問(wèn)對(duì)象的數(shù)據(jù)成員,顯式傳入對(duì)象的地址即可。例如:
class Hack
{
private:
int x;
public:
int get_x();
static void func(Hack * pthis); // 靜態(tài)成員函數(shù)
void func2(); // 非靜態(tài)成員函數(shù)
};
void Hack::func(Hack * pthis)
{
int y = pthis->get_x(); // 訪問(wèn)對(duì)象的數(shù)據(jù)成員
}
這個(gè)方法在大多數(shù)情形下都能行得通,但有時(shí)候成員函數(shù)不能聲明為靜態(tài),也就是說(shuō)成員函數(shù)是虛函數(shù)或者正在使用不能修改的第三方類(lèi)。遇到這種情況時(shí),用方法一解決問(wèn)題就比較難了。
其實(shí)用靜態(tài)成員函數(shù)做線程函數(shù)還不錯(cuò),可以在調(diào)用函數(shù)時(shí)用param傳入this指針,然后在線程函數(shù)中用類(lèi)型轉(zhuǎn)換轉(zhuǎn)換成指向該類(lèi)的指針,這時(shí)該指針就可以訪問(wèn)非靜態(tài)變量和私有變量了
方法二:處理非靜態(tài)成員函數(shù)
假設(shè)需要在單獨(dú)的線程中調(diào)用類(lèi)Hack的非靜態(tài)成員函數(shù)func2()。不用直接傳遞成員函數(shù)的地址到thr_create(),聲明一個(gè)帶 void* 參數(shù)的普通函數(shù)intermediary(void*),然后調(diào)用它:
void intermediary(void*);
接著創(chuàng)建一個(gè)結(jié)構(gòu),結(jié)構(gòu)定義如下:
struct A
{
Hack * p; //類(lèi)對(duì)象指針
void (Hack::*pmf)(); // 成員函數(shù)指針
};
創(chuàng)建一個(gè)結(jié)構(gòu)實(shí)例,用希望的對(duì)象地址和成員函數(shù)地址填充結(jié)構(gòu)(有關(guān)詳細(xì)的成員函數(shù)指針內(nèi)容請(qǐng)參見(jiàn)VC知識(shí)庫(kù)中的其它文章)。
A a; // 結(jié)構(gòu)實(shí)例
Hack h; // 創(chuàng)建對(duì)象
//填充結(jié)構(gòu)
a.p = & h;
a.pmf = &Hack::func2; // 取成員函數(shù)地址
現(xiàn)在回過(guò)頭來(lái)實(shí)現(xiàn)intermediary()函數(shù):
void intermediary(void* ptr)
{
A* pa=static_cast < A* > (ptr); // 強(qiáng)制轉(zhuǎn)換 p 為 A*
Hack* ph=pa->p; // 從A中析取Hack對(duì)象地址
void (Hack::*pmf)()=pa->pmf; // 析取 ptr 到成員函數(shù)
(ph->*pmf)(); // 調(diào)用成員函數(shù)
}
最后將intermediary()的地址傳遞到thr_create():
pthread_create (&ptid, NULL, intermediary, NULL );
pthread_create()調(diào)用函數(shù)intermediary()并將A的地址傳遞給它。intermediary()再?gòu)钠渲羔槄?shù)中展開(kāi)結(jié)構(gòu)A并調(diào)用希望的成員函數(shù)。這種間接方式的處理可以安全地在單獨(dú)線程中啟動(dòng)成員函數(shù),即便是線程庫(kù)不支持成員函數(shù)。如果需要調(diào)用不同類(lèi)的不同成員函數(shù),可以將結(jié)構(gòu)A轉(zhuǎn)換成類(lèi)模板,將函數(shù)intermediary()轉(zhuǎn)換成函數(shù)模板。從而編譯器便會(huì)自動(dòng)產(chǎn)生大多數(shù)樣板文件代碼。
第三種方法:
以將線程函數(shù)申明成友員函數(shù),這樣可以傳入該類(lèi)的指針,訪問(wèn)類(lèi)的成員;
總結(jié)
以上是生活随笔為你收集整理的linux线程创建 类函数吗,linux多线程创建时使用类成员函数作为参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 手机 linux 备份软件有哪些,八款免
- 下一篇: 普通java跑到linux上,JAVA在