我有处理包的类:
typedef void (*FCPackageHandlerFunction)(FCPackage*);
class FCPackageHandlers{
...
void registerHandler(FCPackage::Type type, FCPackageHandlerFunction handler);
void handle(FCPackage* package);
...
QHash<FCPackage::Type, FCPackageHandlerFunction> _handlers;
};
然后我有一个接收包的服务器类。现在我想注册一个处理包的函数。但是这个函数必须有一个服务器实例用于其他变量。
所以我试试这个:
struct FCLoginHandler{
FCServer* server;
FCLoginHandler(FCServer* server){
this->server = server;
}
void operator()(FCPackage* package){
std::cout << "Received package: " << package->toString().data() << "\n";
}
};
...
FCServer::FCServer(){
_handlers.registerHandle(FCPackage::Login, FCLoginHandler(this));
}
但后来我收到了这个错误:
error: no matching function for call to 'FCPackageHandlers::registerHandler(FCPackage::Type, FCLoginHandler)'
note: candidates are: void FCPackageHandlers::registerHandler(FCPackage::Type, void (*)(FCPackage*))
有人知道正确的解决方案吗?
答案 0 :(得分:2)
您正在尝试将函数对象存储在函数指针中,而这是不可能的。您应该存储std::tr1::function
代替:
#include <functional>
typedef std::tr1::function<void(FCPackage*)> FCPackageHandlerFunction;
class FCPackageHandlers{
...
void registerHandler(FCPackage::Type type, FCPackageHandlerFunction handler);
void handle(FCPackage* package);
...
QHash<FCPackage::Type, FCPackageHandlerFunction> _handlers;
};
如果你还没有访问std :: tr1的话,Boost中有一个类似的function
类。
另外,考虑使用boost::bind
和常规函数来避免必须创建自己的函数对象(如FCLoginHandler
:
void handle_FC_login(FCServer* server, FCPackage* package)
{
std::cout << "Received package: " << package->toString().data() << "\n";
// You can use server if you need it
}
FCServer::FCServer()
{
_handlers.registerHandle(FCPackage::Login,
std::tr1::bind(&handle_FC_login, this, _1));
}
std::tr1::bind
也可在Boost中使用,如果您无法访问,则可以始终使用std::bind2nd
。
编辑:由于您无法修改FCPackageHandlerFunction
的类型,您的最佳镜头可能是添加另一个存储与每个函数指针关联的数据的哈希:
typedef void (*FCPackageHandlerFunction)(FCPackage*);
class FCPackageHandlers{
...
void registerHandler(FCPackage::Type type, FCPackageHandlerFunction handler,
FCServer * func_data);
void handle(FCPackage* package);
...
QHash<FCPackage::Type, FCPackageHandlerFunction> _handlers;
QHash<FCPackageHandlerFunction, FCServer*> _handler_func_data;
};
// The server will be passed by the package handler which will
// extract it from the _handler_func_data hash
void handle_FC_login(FCServer* server, FCPackage* package)
{
std::cout << "Received package: " << package->toString().data() << "\n";
}
FCServer::FCServer(){
_handlers.registerHandle(FCPackage::Login, &handle_FC_login, this );
}
据推测,这是您必须实施FCPackageHandlers::handle
:
void FCPackageHandlers::handle(FCPackage * package)
{
// Query function
FCPackageHandlerFunction func = _handlers[package->GetType()];
// Query associated data
FCServer * server = _handler_func_data[func];
// Call handler
func(server, package);
}