最近表示有點... 無聊吧XD
不能停止學習啊~ 慢慢學慢慢進步吧~
除了學習有點停止之外,最近也體認到了一些... 人際關係上的問題吧
真的是活越久看得越多啊... 人這種生物真的很奇妙
明明以前是個單純善良的人,開始健身會打扮、賺了點錢,有女森開始貼上來之後,就變成另外一個人了
充滿了心機與自以為是的態度卻渾然不覺... 還講的自己像個聖人一樣
我看了真的只能搖頭,跟他講他還會覺得自己沒問題 (攤手
果然有自信之餘,也不能忘記自己原本的樣子啊
我還是繼續當那個我認為很弱小的同學好了
我只能好好鞭策自己成為好的那一種,不好的就當作警惕並遠離吧
回到正題,今天來看的是callback function
這個東西說白了就是利用"函式指標"來讓物件之間能夠傳送資料或是進行溝通
比如說今天有一個server和client,我們要讓server在某些情況下去通知client來做一些事情
當然我第一個會想到用觀察者模式啦... 但那也是一個方法就是了
如果是在兩個不同的模組,比如說在兩個dll裡的物件,用callback funtion就是相對方便的一種選擇
(前東家的專案裡就有這種作法)
比較傳統的方式呢,就是在server裡面定義一個callback function的長相,並且設定一個member
大概像是這樣:
typedef void (*pClientCallbackFunc)(int);
class server {
public:
void setCallbackFunc(pClientCallbackFunc callbackfunc);
void callback2Client(int i);
private:
pClientCallbackFunc m_callbackFunc;
}
這樣就有一個callback的member了,而他的長相就是typedef的那樣,就是一個長那樣的函式指標
而client呢可能就是長這個樣子:
class client {
public:
static void callbackFunc(int i) {
cout << "callback : " << i << endl;
}
}
然後怎麼把client的callbackFunc設定到server呢,簡單說就是把client的callbackFunc的指標存到server的m_calbackFunc的地方
這樣server就可以去呼叫client的callbackFunc了:
void setCallbackFunc(pClientCallbackFunc callbackfunc) {
m_calbackFunc = callbackfunc;
}
這邊特別提一下,如果client的callbackFunc(int i)不是static,然後把它設定進去的話,編譯器就會告訴你有error...
因為在C++裡面有一些特性的關係,這個callbackfunc只能是一個static member function
原因大概是在C++中在呼叫member function的時候其實會偷偷用到this這個指標,也就是物件本身
必須要有物件本身的指標才能呼叫那個物件的member function
所以在編譯的時候用上述的寫法其實是沒辦法符合這個規定的,因此會跳出error
(但其實比較新版的C++已經可以輕鬆解決這件事了,稍後會提到)
一個可行的方式就是將那個member function設成static member function
因為static member function就是所有這個class共用的,因此在呼叫的時候並不需要this
所以callback2Client大概是長這樣:
void callback2Client(int i) {
m_callbackFunc(i);
}
這樣在setCallbackFunc(&client::callbackFunc)之後,就可以使用callback了
但這邊有另一個問題,如果我在callback的時候想使用client這個物件的member要怎麼辦呢
這時候就要用一點小技巧,也就是在setCallbackFunc的時候把client的指標傳進去並存起來:
void setCallbackFunc(pClientCallbackFunc callbackfunc, void* this_ptr) {
m_client = static_cast<client*>(this_ptr);
m_calbackFunc = callbackfunc;
}
這個m_client的型態就是client*,也就是一個指標,是server的一個member
這樣在callback2Client的時候,就可以去使用一些client物件的member:
void callback2Client(int i) {
m_callbackFunc(i);
// m_client-> ....
}
大概就是這樣吧,雖然說這是很舊的用法,之後大概沒機會用到,不過有些觀念還滿有趣的
下一篇會用比較新的方式來實作,比較簡單也明瞭,就之後再說吧