typedef void (*CALLBACK)();
class Filter
{
public:
void callback()
{
cout << "callback" << endl;
}
};
void SetCallback(CALLBACK pCallBack )
{
pCallBack();
}
int main()
{
Filter f;
SetCallback(f.callback);
}
Run Code Online (Sandbox Code Playgroud)
主要是SetCallback(f.callback); 声明给出了错误.任何人都可以帮我解决这个问题
问题是成员函数不是没有参数的普通函数,因为它总是有隐含this参数.
如果您遇到需要普通回调函数但没有用户上下文参数的遗留C接口(void*函数只是传递给回调),则会出现问题.
如果你有用户上下文,那很容易.将对象指针作为上下文传递,并使用包装函数作为实际回调:
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);
}
Run Code Online (Sandbox Code Playgroud)
如果您没有上下文,可以选择以下选项:
qsort().至少这种方式,您不会遇到线程安全问题.仍然不是长时间回调的选择.最后一个选项仍然有很多缺点:它是非常特定于平台的,甚至可能根本不用于某些(你不能在iOS,AFAIK中禁用执行保护),它是特定于CPU的(因为你需要生成正确的代码)对于每个),存在管理存根的内存的问题.另一方面,有时它是唯一可行的.Delphi有时会为它的窗口和钩子程序做这种事情,而ATL也是如此.
这是我用来实现对成员函数指针的回调的方法。
它可能需要 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;
}
Run Code Online (Sandbox Code Playgroud)
您应该考虑回调到底是什么以及如何调用成员函数。
当您提供回调函数时,您只需提供稍后将使用您通常无法控制的参数进行调用的函数的地址。
当调用成员函数时,它的第一个参数是指针this,即对调用该方法的对象的引用。
这就是为什么不能使用成员方法作为回调的原因。您只能使用不需要特殊参数(对于程序员来说是隐式的,但从编译器角度来看是真实的)的真正函数或静态成员函数this。