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