咱們常常會把一些耗時的操做放到線程中去執行,當任務執行完畢後就須要通知主線程,通知的方式有不少,在windows平臺上能夠使用消息機制,若是不想依賴平臺API,讓代碼具備良好移植性,使用回調函數也是一種方法。windows
(1)定義函數指針類型函數
typedef void(*pResult)(int);this
(2)在類的內部定義一個函數指針對象線程
private:指針
pResult m_ResultEvent;對象
(3)添加一個函數用來指定回調函數繼承
void setResultEvent(pResult event)回調函數
{io
m_ResultEvent=event;event
}
(4)在線程任務完成後回調函數通知主線程
void run()
{
//do something
if(m_ResultEvent)
m_ResultEvent(1);
}
(5)在主線程中定義回調處理函數
須要注意的是函數只能定義爲靜態函數,只有全局函數或靜態函數才能做爲函數指針傳遞。
class MainObject
{
public:
MainObject();
private:
ThreadObject m_Thread;
int m_Status;
static void doResult(int status);
}
MainObject::MainObject()
{
m_Thread.setResultEvent(doResult);
}
這樣回調的功能就基本實現了。可是若是回調函數只能傳靜態函數,那麼在回調函數中如何與實際的對象聯繫呢。
咱們能夠把對象做爲回調函數的一個參數,這樣經過調用這個參數就能夠實現對此對象的訪問了。能夠將上面的回調函數作一下改造。
typedef void(*pResult)(const void *p,int);
修改線程設置函數,傳入對象指針,並保存
private:
void * m_Object;
void setResultEvent(void *p,pResult event)
{
m_ResultEvent=event;
m_Object=p;
}
在調用的時候將對象this指針傳入:
MainObject::MainObject()
{
m_Thread.setResultEvent(this,doResult);
}
//將對象指針做爲參數傳入回調函數中
void run()
{
//do something
if(m_ResultEvent)
m_ResultEvent(m_Object,1);
}
//在處理函數中將void*指針強轉爲須要的對象類型:
void MainObject::doResult(const void *p,int status)
{
MainObject *obj=(MainObject *)p;
obj->m_Status=status;
}
以上就是C++中對象回調通知的方式,回調函數主要使用了函數指針的概念,實際在C語言中就已存在,C++繼承了這種機制,可是因爲函數只能傳入靜態的或全局的,因此封裝性並很差,類型強制轉換也顯得繁瑣。在C++中有新的機制能夠實現類似的功能,就是利用std::function和std::bind來實現。