!!!注意!!!
これは思いついたことを試しにやってみたらそれっぽく動いたというお話です。
今はstd::functionとstd::bindが標準搭載されていますのでそちらを使いましょう。
現在、GUIアプリ+ゲームを作るためのフレームワークを新たに製作中です。
そのフレームワークに組み込むコールバック機構を考案中なのですが、それについての備忘録とか。
staticなメンバ関数をコールバックに設定するのは実に簡単です。
引数にthisを渡してやって、それをキャストすればいいだけです。
実際、コールバックを使用することが前提のAPIなどはそういった運用を想定して void* などを引数に加えています。
しかし、非staticなメンバ関数をコールバックで呼ぶにはもう少し工夫が必要です。
そこでいろいろ方法を考えてみました。
・メンバ関数の実体自体はメモリ上のどっかに存在する
・でもそれがどのインスタンスのものかがわからない
・インスタンスを判別するにはthisポインタが必要
・じゃあthisポインタと関数のアドレス、この2つがあれば呼べるんじゃね?
というわけでこんなテストコードを作ってみました。
一応ちゃんと呼び出しはできているっぽいです。
コンパイラは VisualC++2005 EE です。
class CCallBack { private: typedef void (CCallBack::*CCallBack::cbFunc)(void); CCallBack* m_inst; cbFunc m_cb; public: template void Regist( T1& inst, T2 cb ) { m_inst = (CCallBack*)&inst; m_cb = (cbFunc)cb; } void Exec( void ) { (m_inst->*CCallBack::m_cb)(); } }; class CTest { public: void print( void ) { printf( "うっうー\n" ); } }; int _tmain(int argc, _TCHAR* argv[]) { CTest test; CCallBack cb; cb.Regist( test, &CTest::print ); cb.Exec(); }
ええんかな、こんなんで(^^;
ツッコミとかありましたら是非コメントしてやってください。
2009年8月8日 追記:
ここからさらに進化させて、引数の型や数、戻り値などの正当性が保証されるように改善。
実用的になってきたかな・・・?
うっうー・・・ってwww
テストコードにも遊び心を忘れてはいけないのですw