gl5_progのメモ

自分のためのメモとかまとめとか

メンバ関数ポインタのアップキャスト

クラスAのメンバ関数ポインタを受け取るところにクラスAを継承したクラスBのメンバ関数ポインタを渡したい場合、つまり、メンバ関数ポインタをアップキャストしたい場合はstatic_castを使えばいいらしいです。
http://ideone.com/dm8iQ9

#include <stdio.h>
 
class A
{
public:
    virtual ~A(){}
};
 
class B : public A
{
public:
    void Func(void){ printf( "B Func();\n" ); }
};
 
typedef void(A::*A_Callback)(void);
 
class C
{
public:
    void SetCallback( A* pA, A_Callback callback )
    {
        m_pA = pA;
        m_Callback = callback;
    }
    void Do( void )
    {
        (m_pA->*m_Callback)();
    }
    A*         m_pA;
    A_Callback m_Callback;
};
 
int main( void )
{
    B b;
    C c;
    /* error
    c.SetCallback( &b, &B::Func );
    */
    c.SetCallback( &b, static_cast<A_Callback>(&B::Func) );
    c.Do();
    return 0;
}

参考

メンバ関数ポインタをアップキャストするときの注意点として、そのメンバ関数ポインタの呼び出しに使うポインタ(thisになるポインタ)が正しくなくてはいけないということです。ここでいう正しいとは、 static_castする前のクラスあるいはその派生クラスを指すものでなくてはいけないということです。 具体的には以下のコードの2回目のSetCallbackはダメです。
http://ideone.com/ooK2Jr

ちなみにメンバ関数ポインタのダウンキャストは明示的なキャストなしで可能なようです。 通常のアップキャスト(明示不要)/ダウンキャスト(要明示)の場合と逆ですね。
http://ideone.com/iFyvuL