2016-04-19 4 views
1

Я хочу передать метод в качестве аргумента метода, который принимает Int и возвращает силу:Как передать указатель на метод в качестве параметра?

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

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

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

Внутри test() я получаю эту ошибку:

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

Как вы могли бы назвать 'B :: Done' в' A', если бы вы смогли его принять? – Holt

ответ

4

Вы не можете передать нестатический метод функции, которая принимает указатель на функцию. Функции и методы - это две совершенно разные вещи. Чтобы вызвать нестатический метод, вы должны, очевидно, иметь объект, метод которого вы вызываете.

Если в вашем примере Done() является методом статического класса, то да, вы можете передать его таким образом, поскольку статический метод класса - это просто другое имя для функции.

Можно иметь указатель на метод класса:

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

} 

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

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

Но для того, чтобы вызвать метод класса, вам нужен объект, метод которого для вызова:

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

Я м, используя следующий код. Это не красиво, но вы просите 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 с и Callback класса, который создан для каждый type (A и B в этом случае).

Это позволяет поддерживать метод любого типа в векторах, массивах или списках абстрактных обратных вызовов.

+0

Нет, я не получил дополнительный аргумент (думаю, 'std :: mem_fun_t' было достаточно). – Holt

Смежные вопросы