2010-02-09 24 views
2

我有類處理包:額外數據函數指針

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*)) 

有誰知道正確的解決方案?

回答

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; 
}; 

有一個類似function類在加速的情況下,你沒有進入標準:: TR1呢。

而且,考慮使用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也在加速可用,如果你沒有訪問,要麼你總是可以使用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); 
} 
+0

事情是,我不能改變FCPackageHandlerFunction類型。還有其他解決方案嗎? – VDVLeon 2010-02-09 13:55:34

+0

@VDVLeon - 看我的編輯。 – Manuel 2010-02-09 14:13:31