繁体   English   中英

C ++将派生类的成员指针转换为基类指针

[英]c++ cast member pointer of derived Class to base class pointer

我目前正在使用HttpServer并遇到以下问题:

我想注册我的控制器,当我收到请求时,我想检查那些控制器中是否有一个针对所请求URL的处理程序,然后调用该处理程序。

到目前为止,还不错,但是我不知道如何用c ++来解决它,而在PHP中,这很容易。

在Easteregg控制器函数getControllerCallbacks中,我想返回可用的回调,但由于无法将派生类的成员函数指针转换为基类(控制器)的成员函数指针(EastereggController),因此无法编译。 我曾考虑过将ControllerCallback设置为“模板类”,但随后我必须知道ControllerHandler中Controller的类,我不知道,因为我有一个std :: vector

我是C ++的新手,也许我忽略了一些东西。

现在是我的代码:

控制器

#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);

只需加上括号即可,现在可以使用了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM