前幾天在用 libFLAC 的時候[?],它要求 client 註冊一個 callback 給它,prototype 長這樣:
可以看到最後一個
typedef FLAC__StreamDecoderWriteStatus (* FLAC__StreamDecoderWriteCallback) (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data);看起來很複雜,其實不會,就是個 function pointer 的 typedef 而己[?]。
可以看到最後一個
void * client_data
是用來接受 client 的資料用的,先接 void * 再轉成自己要的型別,算是 C 的老手法了。
Well, 在 C++ 上使用時就沒有那麼簡單。第一個問題是 member function 需要實體才能使用。
簡單一個想法是宣告一個 struct,把實體和 pointer to member function 包起來,再傳給這個 callback function。不過一來這有點麻煩,二來你不能呼叫用 protected 或 private 修飾的 members。
沒關係,我們有 friend!
嗯,不好意思,這的確是可以動,不過真的很爛。
沒關係,我們有 friend!
嗯,不好意思,這的確是可以動,不過真的很爛。
還好我們還有另一顆子彈,就是 static member function。static member 不需要實體,且 member function 可以存取 class 內所有 member,這樣就一次解決了兩個問題。
所以我們的 callback 會長這樣:
不要譴責我沒用 dynamic_cast,我百分之百確定 client_data 是 FlacReader 好嗎?
所以我們的 callback 會長這樣:
static FLAC__StreamDecoderWriteStatus FlacReader::writeCallback_ (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { FlacReader * self = static_cast< FlacReader * >( client_data ); // blah blah }client_data 那裡傳 this 就好。
不要譴責我沒用 dynamic_cast,我百分之百確定 client_data 是 FlacReader 好嗎?
這不是 coder 卻不確定 binary object (which is pointed to by a void pointer) 的實際型別的問題. 這個狀況用不了 dynamic_cast.
回覆刪除對啊 ... 有些書的建議把 dynamic_cast 無限上綱,好像多型指標不用 dynamic_cast 就一定爆炸。如果完全確定它指向哪個型別,我想用 static_cast 就夠了。
回覆刪除