C++ 带有额外数据的函数指针

C++ 带有额外数据的函数指针,c++,qt4,C++,Qt4,我有一个处理包的类: typedef void (*FCPackageHandlerFunction)(FCPackage*); class FCPackageHandlers{ ... void registerHandler(FCPackage::Type type, FCPackageHandlerFunction handler); void handle(FCPackage* package); ... QHash<FCPackage::T

我有一个处理包的类:

typedef void (*FCPackageHandlerFunction)(FCPackage*);
class FCPackageHandlers{
    ...
    void registerHandler(FCPackage::Type type, FCPackageHandlerFunction handler);
    void handle(FCPackage* package);
    ...
    QHash<FCPackage::Type, FCPackageHandlerFunction> _handlers;
};

有人知道正确的解决方案吗?

您试图将函数对象存储在函数指针中,但这是不可能的。您应该存储一个
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::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 );
}

问题是,我无法更改FCPackageHandler函数类型。还有其他解决办法吗?
#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;
};
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)); 
}
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 );
}
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);
}