c++ 将派生 Class 的成员指针转换为基 class 指针
c++ cast member pointer of derived Class to base class pointer
我目前正在使用 HttpServer 并遇到以下问题:
我想注册我的控制器,当我收到请求时,我想检查其中一个控制器是否具有所请求的处理程序 URL,然后调用该处理程序。
到目前为止一切顺利,但我不知道如何在 c++ 中解决它,在 PHP 中会很容易。
在 Easteregg 控制器函数 getControllerCallbacks 中,我想 return 我的可用回调,但它无法编译,因为我无法将派生 class 的成员函数指针转换为成员函数基class(控制器)的指针(EastereggController)。
我考虑过将 ControllerCallback 设置为 "template class",但我必须知道 ControllerHandler 中控制器的 class,我不知道,因为我有一个 std::vector
我是 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;
}
}
我终于找到了答案(这是我不得不承认的语法错误)
在尝试不同的解决方案时(在此处发布之前),我得到了以下代码片段:
EastereggController.cpp
callback.handlerFunctionPtr = reinterpret_cast<HttpServer::Reply HttpServer::Controller::*>(&EastereggController::easteregg);
语法错误,但我没有注意到它,因为我有以下编译错误:
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);
刚刚添加了括号,现在可以使用了。
我目前正在使用 HttpServer 并遇到以下问题:
我想注册我的控制器,当我收到请求时,我想检查其中一个控制器是否具有所请求的处理程序 URL,然后调用该处理程序。
到目前为止一切顺利,但我不知道如何在 c++ 中解决它,在 PHP 中会很容易。
在 Easteregg 控制器函数 getControllerCallbacks 中,我想 return 我的可用回调,但它无法编译,因为我无法将派生 class 的成员函数指针转换为成员函数基class(控制器)的指针(EastereggController)。 我考虑过将 ControllerCallback 设置为 "template class",但我必须知道 ControllerHandler 中控制器的 class,我不知道,因为我有一个 std::vector
我是 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;
}
}
我终于找到了答案(这是我不得不承认的语法错误)
在尝试不同的解决方案时(在此处发布之前),我得到了以下代码片段:
EastereggController.cpp
callback.handlerFunctionPtr = reinterpret_cast<HttpServer::Reply HttpServer::Controller::*>(&EastereggController::easteregg);
语法错误,但我没有注意到它,因为我有以下编译错误:
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);
刚刚添加了括号,现在可以使用了。