2012-05-11 2 views
10

Вот код:станд :: функция -> указатель функции

#include <functional> 
using namespace std::tr1; 

typedef void(*fp)(void); 

void foo(void) 
{ 

} 

void f(fp) 
{ 

} 

int main() 
{ 
    function<void(void)> fun = foo; 
    f(fun); // error 
    f(foo); // ok 
} 

Первоначально я должен сделать указатель функции от метода нестатического класса, потому что мне нужно сохранить данные между функциональными призваниями. Я пробовал std::tr1::bind и boost::bind, но они возвращают функциональный объект, а не указатель, который, как я вижу, не может быть «отлит» от чистого функционального указателя. Хотя подпись функции (SetupIterateCabinet) требует чистого указателя func точно.

Мне нужно посоветовать, как решить проблему. Спасибо.

ответ

7

Вы значительно упрощать вашу реальную проблему и превратили свой вопрос в XY problem. Вернемся к вашему real вопрос: как позвонить SetupIterateCabinet с нестатической функцией-членом в качестве обратного вызова.

Учитывая некоторый класс:

class MyClass 
{ 
public: 
    UINT MyCallback(UINT Notification, UINT_PTR Param1, UINT_PTR Param2) 
    { 
     /* impl */ 
    } 
}; 

Для того, чтобы использовать MyClass::MyCallback в качестве третьего аргумента SetupIterateCabinet, вам нужно пройти MyClass* для Context аргумента и использовать обычную функцию регулировочной шайбы, чтобы считать, что Context аргумент и сделать правильная вещь:

UINT MyClassCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) 
{ 
    return static_cast<MyClass*>(Context)->MyCallback(Notification, Param1, Param2); 
} 

int main() 
{ 
    MyClass mc; 
    SetupIterateCabinet(_T("some path"), 0, MyClassCallback, &mc); 
} 
+0

Это работает, спасибо! – fogbit

8

Вы не можете преобразовать std::function в указатель функции (вы можете сделать обратное). Вы должны использовать либо указатели на функции, либо std::function s. Если вы можете использовать std::function вместо указателей, то вам следует.

Это делает ваш код работает:

typedef function<void(void)> fp; 
+0

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

+4

Как вы предлагаете ему изменить 'SetupIterateCabinet' (C API), чтобы взять объект C++? – ildjarn

+0

@ildjarn "Вы должны использовать либо указатели на функции, либо' std :: function'. Если он не может использовать 'std :: function', тогда он должен использовать указатели на функции, если только он не хочет обертывать его' std :: function 'вокруг статических функций, но это не будет красивым. – mfontanini

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