MNAの世界

ブログをリニューアルしました!コメント、リンク、ツイートなどはお気軽にどうぞ。

C/C++

[C++]非staticなメンバ関数をコールバックで呼ぶ方法

投稿日:2009年8月3日 更新日:

!!!注意!!!
これは思いついたことを試しにやってみたらそれっぽく動いたというお話です。
今は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日 追記:
ここからさらに進化させて、引数の型や数、戻り値などの正当性が保証されるように改善。
実用的になってきたかな・・・?

-C/C++


  1. せなみ より:

    うっうー・・・ってwww

  2. MNA より:

    テストコードにも遊び心を忘れてはいけないのですw

comment

リンクが多数含まれていると表示されないのでご注意ください。(スパム対策)

関連記事

no image

浮動小数点のワナ

ただいま絶賛滋賀で作業中です。 片道2時間です。若干キレ気味です。 さて、今回もマージなんぞを任されたわけですが、俺としたことが珍しくトラブってました。 その原因は浮動小数点。 機能の追加によってとあ… 続きを読む

no image

PNGに対応

ついに新フレームワークでの動作を開始したZen-Ichiですが、フルカラー化&高解像度化の影響でロード時間がとてつもなく長くなってしまいました。 これではネオジオCDになってしまいます。 (ちなみに当… 続きを読む

no image

[C++]GetKeyboardState() と DirectInput

会社での待機時間を利用して新フレームワークの製作をちょくちょく進めています。 以前思いついたメンバ関数のコールバック機構を発展させて、イベント通知ギミックを完成させたので、次は入力系統のクラス作成にと… 続きを読む