ホームに戻る
出典 :
「class メンバー関数をコールバックとして渡したい」 - stack overflow 「メンバ関数の関数ポインタを扱う方法」- まくまくC/C++ノート
関連 :
static修飾の使い方
目次 :

まえがき

クラスの非静的( static 修飾されていない)メンバ関数(インスタンスメソッド)は暗黙の引数 this をとる都合上、
C互換の関数(非メンバ関数および静的メンバ関数)とは、関数の型が見かけ上等しくても呼び出しに互換性が無い。
⇒ 非静的メンバ関数をクラス外から関数ポインタ経由で呼び出す場合は、 メンバ関数ポインタを 用いるとともに、
this に相当するクラスインスタンスのアドレスを解決する必要がある。
画像

ケース1 : 既知のクラスのメンバとして呼び出す

上記「まえがき」の修正。
コールバックの登録先( m_pfnCallbackFunc )を「( CReceiver クラスの)メンバ関数ポインタ」とするとともに、
コールバックを「( CReceiver )クラスの関数として」登録し、
コールバックを「呼び出す際に」特定のインスタンスに紐づける。
画像

ケース2 : 静的関数化・クラス情報を隠蔽

コールバックを静的関数(クラスメソッド)とすることで、通常の関数ポインタに代入可能となる(クラス関数ポインタを必要としない)
静的関数からはクラスの非静的メンバにアクセスできない( this が無いため)ので、this に相当するインスタンスポインタを渡す。
ケース1と異なり、CSender は CReceiver について知る必要が無いため、より汎用的に実装できる。
画像

注意が必要な点

::*.*->*の各演算子は関数呼び出しの()よりも優先順位が低いので、関数名全体を()で囲まなければ正常に呼び出されない。
誤 : m_pReceiver ->*CallbackFunc(0, true);
正 : (m_pReceiver->*CallbackFunc)(0, true);