2016-04-19 8 views
1

私はint型を取り、voidを返すメソッドの引数としてメソッドを渡したい:メソッドへのポインタをパラメータとして渡すにはどうすればよいですか?

test()インサイド
void A::SetCallback(void (*callback)(int)) 
{ 
    ..................... 
} 

void B::test() 
{ 
    a->SetCallback(&B::Done); // 
} 

void B::Done(int i) 
{ 
    .......................... 
} 

私はこのエラーを取得する:

Error 1 error C2664: cannot convert parameter 1 from 'void (__thiscall B::*)(int)' to 'void (__cdecl *)(int)' 

私はどのようにStackOverflowにいくつかの例を見てこれを修正するには、C++ 11の要素を使用しますが、アクセス権はありません。
C++ 03を使用してこれを修正するにはどうすればよいですか?

+0

'SetCallback'は空き関数へのポインタをとります。クラスメソッドへのポインタは、オブジェクトへのポインタを暗黙的にパラメータとして取るため、異なっています。 – user463035818

+0

もしあなたがそれを取ることができたら、 'A ::'で 'B :: Done'と呼ぶでしょうか? – Holt

答えて

4

非静的メソッドを、関数へのポインタをとる関数に渡すことはできません。関数とメソッドは全く別のものです。非静的メソッドを呼び出すには、メソッドを呼び出すオブジェクトが必要です。

例では、Done()が静的​​クラスメソッドである場合、静的クラスメソッドは関数の別の名前であるため、この方法で渡すことができます。

クラスメソッドへのポインタを持つことが可能です:私は「

B *object=give_me_a_pointer_to_b_from_somewhere(); 

(object->*callback)(0); 
2

&ClassName::method_nameはポインタを作成し、void(ClassName::*)(int, char*)の型です。

void go(void(ClassName::*parameter_name)(int, char*)); 

go(&ClassName::method_name); 
1

あなたは自由な関数へのポインタに(あなたのケースでタイプvoid (B::*) (int)である)クラスメソッドへのポインタを渡すことはできません。

できる場合はどうなりますか?

void f (void (*g) (int)) { 
    g(2); 
} 

struct A { 
    int x; 
    void foo (int c) { x += c; } 
}; 

f(&A::foo); // Oh oh! Where will I find `x` in the call `g(2)`? 

あなただけBの方法へのポインタをしたい場合は、コールバックタイプに変更する必要があります。

void A::SetCallback(void (B::*callback)(int)) { } 

をしかし、その後、あなたは例えば、あなたのコールバックを呼び出すためにBのインスタンスを必要とする:

B b; 
(b.*callback)(2); 
1

void A::SetCallback(void (B::*callback)(int)) 
{ 

} 

void B::test() 
{ 
    a->SetCallback(&B::Done); // 
} 

void B::Done(int i) 
{ 
    .......................... 
} 

しかし、クラスのメソッドを呼び出すために、あなたがそのメソッドを呼び出すためのオブジェクトが必要です次のコードを使用してください。それはかなりありませんが、C++ 03を求めて:

#include <iostream> 
#include <vector> 
#include <functional> 

class AbstractCallback { 
public: 
    virtual void call(int arg) = 0; 
}; 

template <class T> 
class Callback : public AbstractCallback { 
public: 
    typedef std::mem_fun1_t<void, T, int> CallbackFunc; 
private: 
    CallbackFunc func; 
    T* object; 
public: 
    Callback(T* _object, const CallbackFunc& _func) 
     : object(_object), func(_func) { 
    } 

    void call(int arg) { 
     func(object, arg); 
    } 
}; 

struct A { 
    void foo(int a) { 
     std::cout << "foo " << a << std::endl; 
    } 
}; 
struct B { 
    void bar(int a) { 
     std::cout << "bar " << a << std::endl; 
    } 
}; 

int main() { 
    A a; 
    B b; 

    AbstractCallback* cbs[2] = { 
     new Callback<A>(&a, std::mem_fun(&A::foo)), 
     new Callback<B>(&b, std::mem_fun(&B::bar)), 
    }; 

    cbs[0]->call(10); 
    cbs[1]->call(22); 

    delete cbs[0]; 
    delete cbs[1]; 

    return 0; 
} 

あなたはへのポインタ(タイプA::*B::*の)メンバ関数を見ることができるようにするために生成されstd::mem_fun sおよびCallbackクラスにラップされています各タイプ(この場合はAB)。

これにより、任意の型のメソッドをベクトル、配列または抽象コールバックのリストに保持できます。

+0

なし、私は余分なargを得られませんでした( 'std :: mem_fun_t'で十分だと思いました)。 – Holt

関連する問題