2016-06-09 180 views
0

我目前工作的一個HttpServer的和有以下問題:C++派生類的劇組成員指針到基類指針

我要註冊我的控制器,當我得到一個請求,我要檢查,如果一個這些控制器具有所請求的URL的處理程序,然後調用處理程序。

到目前爲止這麼好,但我不知道如何用C++解決它,在PHP中它會很容易。

在Easteregg控制器函數getControllerCallbacks我想返回我可用的回調,但它不會編譯,因爲我不能將派生類的成員函數指針強制轉換爲基類的成員函數指針(EastereggController)(控制器)。 我想過要使ControllerCallback成爲一個「模板類」,但我必須知道ControllerHandler中的控制器類,我不知道,因爲我有一個std ::向量

我很公平新的C++,也許我忽略了一些東西。

現在這是我的代碼:

或者Controller.h

#ifndef CONTROLLER_H 
#define CONTROLLER_H 

#include "Config.h" 
#include "Request.h" 
#include "ControllerCallback.h" 

namespace HttpServer { 

class ControllerCallback; 

class Controller { 
    public: 
     Controller(); 
     virtual std::vector<ControllerCallback> getControllerCallbacks() = 0; 

    private: 
     Config *config; 
     const Request *request; 
}; 
} 
#endif // CONTROLLER_H 

EastereggController.h

#ifndef EASTEREGGCONTROLLER_H 
#define EASTEREGGCONTROLLER_H 

#include "../HttpServer/Controller.h" 

namespace Controller { 

    class EastereggController: public HttpServer::Controller { 
     public: 
      EastereggController() {}; 
      std::vector<HttpServer::ControllerCallback> getControllerCallbacks(); 
      HttpServer::Reply easteregg(); 
    }; 
} 

#endif // EASTEREGGCONTROLLER_H 

EastereggController.cpp

#include "EastereggController.h" 

namespace Controller { 
    std::vector<HttpServer::ControllerCallback> EastereggController::getControllerCallbacks() { 
     std::vector<HttpServer::ControllerCallback> controllerCallbacks; 
     HttpServer::ControllerCallback callback; 

     callback.pathTemplate = "/easteregg"; 
     callback.handlerFunctionPtr = &EastereggController::easteregg; 
     return controllerCallbacks; 
    } 

    HttpServer::Reply EastereggController::easteregg() { 
     HttpServer::Reply rep; 
     rep.content.append("you have found an easteregg\n"); 
     rep.status = HttpServer::Reply::ok; 
     rep.headers.resize(2); 
     rep.headers[0].name = "Content-Length"; 
     rep.headers[0].value = std::to_string(rep.content.size()); 
     rep.headers[1].name = "Content-Type"; 
     rep.headers[1].value = "text/plain"; 
     return rep; 
    } 
} 

ControllerCallback.h

#ifndef CONTROLLERCALLBACK_H 
#define CONTROLLERCALLBACK_H 


#include "Reply.h" 
#include <string> 

namespace HttpServer { 

    class Controller; 

    class ControllerCallback { 

     public: 
      ControllerCallback() 
       : pathTemplate("") {}; 
      //,handlerFunctionPtr(nullptr){} 

      std::string pathTemplate; 
      Reply(Controller::*handlerFunctionPtr)(); 
    }; 
} 

#endif 

ControllerHandler.h

#ifndef CONTROLLERHANDLER_H 
#define CONTROLLERHANDLER_H 

#include <vector> 
#include <string> 
#include "Controller.h" 
#include "Config.h" 
#include "Request.h" 
#include "Reply.h" 

namespace HttpServer { 

    class ControllerHandler { 
     public: 
      ControllerHandler(Config &conf); 
      void registerController(Controller &controller); 
      bool invokeController(std::string requestPath, Request &req, Reply &rep); 

     private: 
      Config &config; 
      std::vector<Controller *> controllers; 

    }; 

} 

#endif // CONTROLLERHANDLER_H 

ControllerHandler.cpp

#include "ControllerHandler.h" 
#include "Controller.h" 
#include "PathHandler.h" 

namespace HttpServer { 
    ControllerHandler::ControllerHandler(Config &conf) 
     : config(conf) { 
    } 

    void ControllerHandler::registerController(Controller &controller) { 
     controllers.push_back(&controller); 
    } 

    bool ControllerHandler::invokeController(std::string requestPath, Request &req, Reply &rep) { 
     PathHandler pathHandler(requestPath, ':'); 

     for(Controller *controller : controllers) { 
      std::vector<ControllerCallback> callbacks = controller->getControllerCallbacks(); 
      for(ControllerCallback controllerCallback : callbacks) { 
       if(pathHandler.compare(controllerCallback.pathTemplate)) { 
        rep = ((*controller).*(controllerCallback.handlerFunctionPtr))(); 
        return true; 
       } 
      } 
     } 

     return false; 
    } 
} 
+0

我認爲指向成員函數的指針是基於類中的靜態偏移量,它不適用於多態類型。你需要一個虛擬函數 - 只傳遞一個引用/指向該對象的指針,然後調用該對象的虛擬Reply()方法。 –

+0

所以你的意思是我應該實現處理函數被發現到類中的邏輯? –

+0

我只是建議給它一個對象,然後在該對象上調用Reply()。您仍然可以使用相同的邏輯來查找處理請求的正確對象。 –

回答

0

我終於發現我有下面的代碼片段答案(這是一個語法錯誤,我不得不承認)

在嘗試不同的解決方案(在這裏發帖前):

EastereggController.cpp

callback.handlerFunctionPtr = reinterpret_cast<HttpServer::Reply HttpServer::Controller::*>(&EastereggController::easteregg); 

這是syntactilly錯了,但我還沒有注意到這一點,因爲我有以下編譯錯誤:

error: invalid cast from type 'HttpServer::Reply (Controller::EastereggController::*)()' to type 'HttpServer::Reply HttpServer::Controller::*()' 
    callback.handlerFunctionPtr = reinterpret_cast<HttpServer::Reply HttpServer::Controller::*()>(&EastereggController::easteregg); 

現在正確的版本:

callback.handlerFunctionPtr = reinterpret_cast<HttpServer::Reply(HttpServer::Controller::*)()>(&EastereggController::easteregg); 

剛剛添加的括號,現在它的工作原理。

相關問題