C++函数回调:无法从成员函数转换为函数签名
C++ Function Callbacks: Cannot convert from a member function to a function signature
我使用的是第三方库,它允许我注册某些事件的回调。register函数看起来像这样。它使用回调签名。
typedef int (*Callback)(std::string);
void registerCallback(Callback pCallback) {
//it gets registered
}
我的问题是,我想注册一个成员函数作为回调,类似于
struct MyStruct {
MyStruct();
int myCallback(std::string str);
};
MyStruct::MyStruct() {
registerCallback(&MyStruct::myCallback);
}
int MyStruct::myCallback(std::string str) {
return 0;
}
当然,编译器抱怨说
错误C2664:"registerCallback":无法将参数1从"int(__thiscall MyStruct::*((std::string("转换为"Callback">
我一直在研究诸如函数和绑定之类的boost库,但似乎没有一个能够做到这一点。我一直在谷歌上搜索答案,但我甚至不知道该怎么称呼,所以这并没有多大帮助。
提前谢谢。
您试图将成员函数指针作为普通函数指针传递,但这是不起作用的。成员函数必须将this
指针作为隐藏参数之一,而普通函数则不然,因此它们的类型是不兼容的。
您可以:
- 更改参数的类型以接受成员函数,并接受实例作为调用对象
- 停止尝试传递成员函数并传递正常函数(可能通过使函数
static
( - 有一个普通函数,它接受类的一个实例、一个成员函数指针和一个
std::string
,并使用类似boost的bind
之类的东西来绑定前两个参数 - 让回调注册函数接受一个functor对象或
std::function
(我想这就是名称( - 许多其他方式,我不会在这里详细介绍,但你会明白的
成员函数不能转换为正常函数,这是有充分理由的。如果您的设计允许,那么将MyStruct::myCallback()
作为static
成员方法,代码应该可以正常工作。
struct MyStruct {
...
static int myCallback(std::string str);
^^^^^^
};
由于回调的实际函数类型的硬编码不灵活,您无法使用任何常规的调整或绑定技巧来帮助您。第三方库确实希望您传入一个非成员函数,但您无能为力。您可能需要考虑为什么要将成员函数的地址传递给它,以及您对库的设计或使用是否会发生变化。
如果您只需要设置一个回调,那么一种选择是使用一个静态或命名空间私有函数,该函数引用一个单例实例指针,并在回调时使用该指针进行调度。
如果你需要多个项目,那么可能会有一个模板来包装这些技巧(这里是未经测试的代码,只是想法(。
template <int which_callback>
struct CallbackHolderHack
{
static int callback_func(std::string str) { dispatchee_->myCallback(str); }
static MyStruct* dispatchee_;
};
template <int which_callback>
MyStruct* CallbackHolderHack::dispatchee_(0);
并使用它:
CallbackHolderHack<0>::dispatchee_ = new MyStruct;
registerCallback(&CallbackHolderHack<0>::callback_func);
取决于您如何使用它……例如,Singlton会简化
struct MyStruct {
static MyStruct& Create() {
static MyStruct m; return m;
}
static int StaticCallBack(std::string str) {
return Create().Callback(str)
}
private:
int CallBack(std::string str);
MyStruct();
};
或者,如果你想拥有许多这样的对象,你有几个选择。在调用回调之前,您需要一种方法来路由它。
既然您使用的是C++,为什么不将回调设置为函子对象呢?然后您可以使用std::mem_fun
。
编辑:似乎std::mem_fun
在最新的C++11标准中已被弃用。因此,如果您有一个新的编译器,std::function
可能是一个更好的解决方案。
有关使用它的提示,请参阅此SO问题。
class ICallBackInterface
{
public:
virtual void FireCallBack( std::string& str ) = 0;
};
std::set<ICallBackInterface*> CallBackMgr;
class MyStruct : public ICallBackInterface
{
public:
MyStruct()
{
CallBackMgr.insert( this );
}
~MyStruct()
{
CallBackMgr.erase( this );
}
virtual void FireCallBack( std::string& str )
{
std::cout << "MyStruct calledn";
}
};
void FireAllCallBack(std::string& str )
{
for ( std::set<ICallBackInterface*>::iterator iter = CallBackMgr.begin();
iter != CallBackMgr.end();
++iter)
{
(*iter)->FireCallBack( str );
}
}
这是使用多态性来实现相同效果的另一种方法
- 如何使用Rcpp将R函数转换为C++函数
- C++函数转换为 C# 函数
- 将 C 函数转换为 C++ 以检查数字是否有效
- C++:从重载函数转换为 std::function
- 将 C 函数转换为C++语言
- C++隐式构造函数转换,后跟类型向上转换
- 将 lambda 函数转换为具有混合 lambda 引入器和参数列表的函子结构
- 通过 Boost Python 将 Python 函数转换为 C++,用作回调
- 如何将 MATLAB 图像处理库内置函数转换为 MATLAB 编码器代码生成不支持的 C++?
- 如何将函数转换为 lambda 函数
- 自定义函数转换错误?
- 将 C# 哈希函数转换为C++
- 将 lambda 函数转换为另一个编译单元中的普通函数会缩短编译时间吗?
- 加快 R 性能或将 R 函数转换为C++函数
- 将成员函数转换为指向成员函数的指针
- 将MATLAB炒作函数转换为C
- Rcpp - 用二进制函数转换数字向量?
- C lambda函数转换误差
- 此语法中的构造函数转换错误
- 将函数转换为find_if lambda