typedef void (*CALLBACK)();
class Filter
{
public:
void callback()
{
cout << "callback" << endl;
}
};
void SetCallback(CALLBACK pCallBack )
{
pCallBack();
}
int main()
{
Filter f;
SetCallback(f.callback);
}
主要是SetCallback(f.callback);声明给出了错误。任何人都可以帮我解决问题
答案 0 :(得分:7)
问题是成员函数不是没有参数的普通函数,因为它总是具有隐式this
参数。
如果遇到需要普通回调函数且没有用户上下文参数(函数只传递给回调的void*
)的遗留C接口,则会出现问题。
如果您确实拥有用户上下文,则很容易。将对象指针作为上下文传递,并使用包装器函数作为实际回调:
typedef void (*CALLBACK)(void*);
class Filter
{
public:
static void CallbackWrapper(void* context) {
static_cast<Filter*>(context)->callback();
}
private:
void callback();
};
int main() {
Filter f;
SetCallback(&Filter::CallbackWrapper, &f);
}
如果您没有上下文,可以选择以下选项:
qsort()
。至少这种方式,您不会遇到线程安全问题。仍然不是长时间回调的选择。最终选项仍有许多缺点:它非常特定于平台,甚至可能根本无法工作(你无法在iOS,AFAIK中禁用执行保护),它是特定于CPU的(因为你需要生成每个的正确代码,并且存在管理存根的内存的问题。另一方面,有时它是唯一可行的。 Delphi有时为它的窗口和钩子程序做这种事情,ATL也这样做。
答案 1 :(得分:3)
这是我用来实现对成员函数指针的回调的方法。
可能需要C ++ 11。
#include <iostream>
#include <string>
#include <functional>
using namespace std;
struct MessageSource
{
function<void(const string& msg)> _callback;
template<typename A, typename B>
void connect(A func_ptr, B obj_ptr)
{
_callback = bind(func_ptr, obj_ptr, placeholders::_1);
}
void send_msg(const string& msg)
{
if (_callback)
_callback(msg);
}
void disconnect()
{
_callback = nullptr;
}
};
struct Printer
{
void print(const string& msg) { std::cout << msg << std::endl; };
};
int main()
{
{
Printer p;
MessageSource s;
s.connect(&Printer::print, &p);
s.send_msg("test");
s.disconnect();
s.send_msg("test again");
}
system("pause");
return 0;
}
答案 2 :(得分:1)
关于“非静态方法”的回调的简单示例:
#include <iostream>
#include <string>
#include <functional>
using namespace std::placeholders;
class Test
{
public:
void SetValue(int i) { v = i;}
int v;
};
int main()
{
Test a { 123 };
std::cout << a.v << std::endl; // print 123
auto _callback = std::bind(&Test::SetValue, &a, _1); // create the callback
_callback(55); // call the callback
std::cout << a.v << std::endl; // print 55
return 0;
}
输出:
123
55
答案 3 :(得分:0)
您应该考虑回调的真正含义以及如何调用成员函数。
当你给出一个回调函数时,你只需要给出一个函数的地址,该函数稍后会被你通常无法控制的参数调用。
调用成员函数时,它的第一个参数是this
指针,它是对调用该方法的对象的引用。
这就是为什么不可以使用成员方法作为回调的原因。您只能使用真正的函数或静态成员函数,这些函数不需要特殊的(对编程人员是隐式的,但在编译器的角度来看是真实的)参数this
。