2016-04-09 18 views
2

シグネチャは同一ですが、異なるクラスの非スタティックメンバ関数の参照を、一致するシグネチャを持つファンクションポインタに割り当てるにはどうすればよいですか?C++ファンクションシグネチャが一致する任意のクラスのメンバ関数へのポインタ

これは、C++標準ライブラリのstd::functionの助けを借りて行うことができます。私はまた、通常のCの関数とstdライブラリからの助けを借りてこれをいつも行います。私はファームウェアを書いており、コードスペースは限られています。 C++標準ライブラリのヘルパーがそれを行うことができれば、純粋にC/C++言語構造(pre C++ 11が望ましい)を使用して手動で行うことができるはずです。私の意図を証明

例コード:

class A { 
public: 
    void ping_event_handler(); 
}; 

class B { 
public: 
    void ping_event_handler(); 
}; 

void A::ping_event_handler_A() { 
    // Handle ping event in A... 
} 

void B::ping_event_handler_B() { 
    // Handle ping event in B... 
} 

void ping_event_handler_C() { 
    // Handle ping event in normal function... 
} 

int main() { 

    // Ping event "pointer to a function that takes no arguments" 
    void (*ping_event)(); 

    A a(); 
    B b(); 

    ping_event = a.ping_event_handler; // Attach class A's handler 
    ping_event();      // Trigger event 

    ping_event = b.ping_event_handler; // Attach class B's handler 
    ping_event();      // Trigger event 

    ping_event = ping_event_handler; // Attach non-class handler 
    ping_event();      // Trigger event 

} 
+0

開始するために、 '( ); '間違っています。これは関数 'a'を宣言しています –

+0

' ping_event = a.ping_event_handler; ' - ' this'に与えるべき値をコンパイラがどのように知っていますか? –

+0

これらのメソッドを静的(オブジェクトの状態を必要としない場合)または仮想(共通基本クラスから継承)と宣言し、関数へのポインタを基本クラスへのポインタで置き換えます。関数へのポインタとメソッドへのポインタを混在させたい場合は、std:functionとしていくつかのラッパーが必要です。 – avsmal

答えて

1

古い方法は、機能

void (*ping_event)(void* userData); 

userDataを渡し、機能、およびuserDataの両方を保存することです。その後、ユーザ側で 、そのクラスでのuserDataをキャストし、それから、任意の方法で呼び出す:

struct my_function 
{ 
    my_function(void (*f)(void*), void* userData) : mF(f), mUserData(userData) 
    {} 

    void set(void (*f)(void*), void* userData) 
    { 
     mF = f; 
     mUserData = userData; 
    } 

    void operator()() { 
     mF(mUserData); 
    } 
    void (*mF)(void*); 
    void* mUserData; 
}; 

とコールサイトで:

template <typename C, void (C::*m)()> 
void my_func_helper(void* userData) 
{ 
    C* c = static_cast<C*>(userData); 
    (c->*m)(); 
} 


int main() 
{ 
    A a; 

    my_function f(&my_func_helper<A, &A::ping_event_handler>, &a); 

    f(); 

    B b; 

    f.set(&my_func_helper<B, &B::ping_event_handler>, &b); 
    f(); 

    f.set(ping_event_handler_c, NULL); 
    f(); 
} 

Demo

+0

よくできました!完璧に動作し、標準ライブラリもサブクラスもありません。関数の呼び出しが引数でどのように見えるかを参考にすることができます。それとも不可能ですか? –

+1

関数のポインタ型を変更し、関数呼び出しを変更する必要があります。[Demo](http://coliru.stacked-crooked.com/a/2458b90c6fad2f52) – Jarod42

関連する問題