typedef void (*CALLBACK)();
class Filter
{
public:
void callback()
{
cout << "callback" << endl;
}
};
void SetCallback(CALLBACK pCallBack )
{
pCallBack();
}
int main()
{
Filter f;
SetCallback(f.callback);
}
在main中,SetCallback(f.callback);语句给出错误。谁能帮我解决这个问题
问题是成员函数不是没有参数的普通函数,因为它总是具有隐式的this
范围。
如果您遇到需要一个不带用户上下文参数(avoid*
该函数只是传递给回调)你有问题。
如果您确实有用户上下文,那就很容易了。传递对象指针作为上下文,并使用包装函数作为实际的回调:
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 中禁用执行保护),它是特定于 CPU 的(因为你需要生成正确的代码)对于每个),并且存在管理存根内存的问题。另一方面,有时这是唯一有效的方法。 Delphi 有时为其窗口和挂钩过程做这种事情,ATL 也这样做。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)