日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++学习笔记之基础---类内声明线程函数的调用

發(fā)布時間:2023/12/20 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++学习笔记之基础---类内声明线程函数的调用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??近日需要將線程池封裝成C++類,類名為Threadpool。在類的成員函數(shù)exec_task中調用pthread_create去啟動線程執(zhí)行例程thread_rounter。編譯之后報錯如下:

spfs_threadpool.cpp:?In?member?function?‘int?Threadpool::exec_task(task*)’:

spfs_threadpool.cpp:174:?error:?argument?of?type?‘void*?(Threadpool::)(void*)’?does?not?match?‘void*?(*)(void*)’

? ? 出現(xiàn)類型不匹配的問題。因為pthread_create需要的參數(shù)類型為void*?(*)(void*),而thread_rounter作為類的成員函數(shù)時其類型是void*?(Threadpool::)(void*)的成員函數(shù)指針。我們知道類的成員函數(shù)在經(jīng)過編譯器處理之后,會變成帶有this指針參數(shù)的全局函數(shù),所以類型注定是不會匹配的。但是如果將thread_rounter聲明為static類型,那么編譯器會將static形式的函數(shù),轉換成不帶this指針的全局函數(shù),所以其類型可以與pthread_create需要的參數(shù)類型相匹配。但是類的靜態(tài)成員函數(shù)無法訪問類的非靜態(tài)成員,不過這可以通過傳遞this指針解決這個問題。

綜上,我的這個問題可以這個樣子解決。

出問題之前的代碼:

void?*thread_rounter(void?*)//線程執(zhí)行函數(shù)

{

???//直接訪問類的成員

}

?

exec_task函數(shù)中調用:

pthread_create(&tid,NULL,thread_rounter,NULL);//啟動線程執(zhí)行例程

?

修復這個問題的代碼:

static?void?*thread_rounter(void?*tmp)/線程執(zhí)行函數(shù)

{

??Threadpool?*p=(Threadpool?*)tmp;

????//通過p指針間接訪問類的非靜態(tài)成員

?

}

?

exec_task函數(shù)中調用:

pthread_create(&tid,NULL,thread_rounter,(void?*)this);//啟動線程執(zhí)行例程

----------------------------------------------------------------------------------------------------------------------

?

在網(wǎng)上搜索一下還有其他的解決方案,摘錄如下,為了以示尊重標明文章來源,感謝原文作者。

?

方案二:

將線程啟動函數(shù)聲明為模板函數(shù)。

摘錄自:http://hi.baidu.com/angelevil2006/item/e1806ec30574ff11515058d1

[cpp]?view plaincopy
  • template?<typename?TYPE,?void?(TYPE::*_RunThread)()?>??
  • void*?_thread_t(void*?param)//線程啟動函數(shù),聲明為模板函數(shù)??
  • {?????
  • ?TYPE*?This?=?(TYPE*)param;?????
  • ?This->_RunThread();?????
  • ?return?NULL;??
  • ?}??
  • ???
  • ?class?MyClass??
  • ?{??
  • ?public:????
  • ?MyClass();???
  • ?void?_RunThread();??
  • ???
  • ?private:????
  • ?pthread_t?tid;????
  • ?};??
  • ???
  • ?void?MyClass::_RunThread()??
  • ?{?????
  • ?this->DoSomeThing();?????
  • ?}??
  • ???
  • ?MyClass::MyClass()??
  • ?{?????
  • ?pthread_create(&tid,?NULL,?_thread_t<MyClass,?&MyClass::_RunThread>,?this);??
  • ?}???????
  • ???
  • ???
  • ?//函數(shù)模版不單可以替換類型本身,還能替換類型的成員函數(shù)。??
  • ?//注意:??????1、名稱只能是_RunThread,不能在指定模版參數(shù)的時候修改;???????????
  • ?//??2、_RunThread只能是public的,除非把_thread_t定義到MyClass的內部。??
  • ???
  • ???
  • ???
  • ?

    采取這個方案放入我的項目中:

    ?

    出問題之前的代碼:

    void?*thread_rounter(void?*)//線程執(zhí)行函數(shù)

    {

    ???//直接訪問類的成員

    }

    ?

    exec_task函數(shù)中調用:

    pthread_create(&tid,NULL,thread_rounter,NULL);//啟動線程執(zhí)行例程

    ?

    修復這個問題的代碼:

    添加public成員函數(shù):

    ?

    void?Run()

    {

    ??//該函數(shù)替換上述thread_rounter的執(zhí)行代碼

    }

    ?

    thread_rounter修改為全局模板函數(shù):

    ?

    template?<typename?TYPE,?void?(TYPE::*Run)()?>

    void?*?thread_rounter(void?*?param)

    {

    ????TYPE?*p=(TYPE*)param;

    ????p->Run();

    ????return?NULL;

    }

    ?

    exec_task函數(shù)中調用:

    pthread_create(&tid,NULL,thread_rounter<Threadpool,&Threadpool::Run>,(void?*)this);

    ?

    總結:

    解決這個問題的關鍵在于想方設法使啟動函數(shù)指針滿足void*(*)(void?*)類型。

    ?

    將啟動函數(shù)改寫成static成員函數(shù)適用于可以修改類的源代碼的情況。

    ?

    而將啟動函數(shù)寫成模板函數(shù)還可以適用于沒有類的源代碼的情況,自己寫一個類,公共繼承自原類,添加啟動函數(shù)為模板函數(shù)即可。

    花了三個工作日把原來寫的一段通信守護進程代碼從過程方法改到了 template class,對于 template 的使用和類的派生明白了不少道理。還有個很受啟發(fā)的一點,就是 C++ 中如何使用類的成員函數(shù)作為創(chuàng)建線程的開始函數(shù)。
    pthread_create 是 POSIX 標準下創(chuàng)建線程的函數(shù),函數(shù)原型是:
    int pthread_create(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void *), void *arg);

    在 C 中,這個函數(shù)使用很簡單,只要定義一個參數(shù)和返回值均為 void * 類型的函數(shù),使用函數(shù)名字作為參數(shù)即可。就算不完全符合,可以使用 (void *(*)(void *)) 將其強制轉換為符合類型檢查規(guī)格的函數(shù)指針。但是,類的非靜態(tài)成員函數(shù)隱含 this 指針作為第一個參數(shù),所以參數(shù)完全不可能轉化為 void * 類型,而 C++ 的類型檢查要比 C 嚴格許多。由于我原來寫的代碼是 C 風格的,自然不會出現(xiàn)類型不符的問題,現(xiàn)在將線程開始函數(shù)封裝到一個模板類中,再創(chuàng)建線程的時候就不能滿足需要了。

    在試了幾種轉換無效之后,從網(wǎng)上搜到一種方法:定義線程開始函數(shù)為類的靜態(tài)成員函數(shù)(static member function),這樣就不隱含 this 指針了,然后將 this 指針從 pthread_create 最后一個參數(shù)傳給開始函數(shù),在函數(shù)中將 void * 類型的 this 指針強制轉換為類指針。看來靜態(tài)成員函數(shù)還是有些妙用的。

    ===================我叫分割線===================

    帶著我媽和我妹在北京城里轉悠了幾天,累得不行。主要原因在我,沒有考慮到身體因素,連著玩消耗太大,再加上自己也沒車沒房,倒公交車和住賓館也要走很遠,費時間又費勁。我都快受不了了,別說我媽了。以后再出去旅游,堅決不會再連著轉三天以上,要么緊緊張張地玩兩天,要么就花時間長點兒,走走歇歇。唉,誰讓咱是窮人呢,又有錢又有閑的日子還沒過上呢!

    今天看了下積壓很久的博客訂閱,同學里開始寫和繼續(xù)寫的人越來越多了。覺得有些文章比較陰沉低迷,因為自己從大三開始心情就老是跌宕起伏,反而在面對這許多次的分別聚首時坦然一些。要不是周熹在散伙飯時候專門招我,也不會哭得那么厲害。散了散了散了吧,沒有離別,怎么會有重逢呢?

    還是在 Yourui 的博客上看到小恪去新疆的消息,要是當面看到他,肯定會玩笑說發(fā)配三千里伊犁充軍去了。這在邊關待了兩年之后,再回來學積分拓撲之類的數(shù)學還能看得下去嗎?都說是命運無常,旅途坎坷卻能看更美風景,只是不知道那關外還是不是大漠孤煙長河落日的大西北?

    剛才去吃飯,走在晚間暖暖的懶洋洋的空氣中,忽然有點兒秋天的感覺。想起 7 年前爸爸送我到商丘一高上學的情景,日子可真快啊!老了,老了!

    http://bbs.chinaunix.net/thread-724023-1-1.html http://blog.solrex.org/articles/class-member-function-as-pthread_create-argument.html

    http://blog.csdn.net/luo6620378xu/article/details/8521940

    總結

    以上是生活随笔為你收集整理的c++学习笔记之基础---类内声明线程函数的调用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。