関数ポインタの使用に問題はありません。ただし、非静的メンバー関数へのポインターは、通常の関数ポインターとは異なります。メンバー関数は、関数に暗黙的な引数として渡されるオブジェクトで呼び出す必要があります。したがって、上記のメンバー関数の署名は
void (aClass::*)(int, int)
使用しようとするタイプではなく
void (*)(int, int)
1つの方法は、メンバー関数を作成することstatic
です。この場合、オブジェクトを呼び出す必要がなく、typeで使用できますvoid (*)(int, int)
。
あなたのクラスの任意の非静的メンバーにアクセスする必要がある場合 と、あなたは関数ポインタに固執する必要があり、例えば、関数がCインタフェースの一部であるため、あなたの最良のオプションは、常に通過させることであるvoid*
関数ポインタとコールを取るあなたの機能にからオブジェクトを取得しvoid*
てメンバー関数を呼び出す転送関数を介してメンバー。
適切なC ++インターフェースでは、関数が任意のクラス型を使用するために、関数オブジェクトのテンプレート化された引数を関数に持たせることを検討したい場合があります。テンプレート化されたインターフェースを使用することが望ましくない場合は、次のようなものを使用するstd::function<void(int, int)>
必要がありますstd::bind()
。たとえば、を使用して、これらに適切に呼び出し可能な関数オブジェクトを作成できます。
クラス型または適切な型のテンプレート引数を使用するタイプセーフなアプローチは、不適切な型へのキャストによるエラーの可能性を取り除くため、インターフェースをstd::function<...>
使用するよりも望ましい方法void*
です。
関数ポインターを使用してメンバー関数を呼び出す方法を明確にするために、以下に例を示します。
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, 0);
foo object;
somefunction(&forwarder, &object);
}