2016-06-09 178 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); 

刚刚添加的括号,现在它的工作原理。

相关问题