関数ポインタ

すぐやり方を忘れるので覚えているうちにメモ。

void hoge(){}
namespace foo{
    void piyo(){}
}
class bar {
public:
    void boon(){}
    static void ban(){}
};

// typedef 戻り値 ポインタの型名(引数リスト); 引数部分の書き方はC/C++の文法に準じる。
typedef void (*FP)();

int main(){
    FP fp1 = hoge; // または &hoge
    FP fp2 = foo::piyo; // または &foo::piyo
    FP fp3 = bar::ban; // または &bar::ban
    void (bar::*fp4)() = &bar::boon; // bar::boonはだめ。ポインタ名(typedefなら型名)の部分にクラス名が必要。
    bar b;
    bar *a = &b;
    
    fp1();
    fp2();
    fp3();
    (b.*fp4)();
    (a->*fp4)();
    
    return 0;
}

グローバル名前空間の関数、特定の名前空間の関数、スタティックメンバ関数は「どこに属しているか」が違うだけで他は同じなので全部が同様の方法で出来る。ってことだと思う。
普通のメンバ関数はどのインスタンスに属している状態で呼ばれているのか分からないと仕事ができない(見当違いのアドレスがthisポインタに入ったりする)ので、所属インスタンスを特定するために適切なインスタンスが必要。
実際にはワケ分からんアドレスがthisに入ったりする前にコンパイラに怒られます\(^o^)/
通常のメンバ関数の時だけポインタ名にクラス名を指定する理由は謎。普通の関数ポインタと区別するためっぽいけど・・・。