如何从另一个类的方法引用一个类的实例,而又不将该实例传递给另一个类的构造函数?

时间:2019-12-05 17:18:17

标签: c++ structure

我正在尝试寻找一种惯用且非冗余的方法,以使服务器根据进程启动时给出的某些命令行选项使用不同的处理程序来读写套接字。这很简单,但是我试图在main()函数中创建一个与命令行选项相对应的类的实例,并在我的处理程序中引用该特定实例。例如,考虑以下代码片段。

PlainServer.hpp

class PlainServer : public TCPServer {
public:
    typedef std::vector<uint8_t> PlainDatabase;
    typedef uint64_t PlainQuery;
    typedef std::vector<uint8_t> PlainReply;

    explicit PlainServer(aio::io_context& io_context);

    PlainReply generate_reply(PlainQuery query);

    void gen_database();

private:
    PlainReply reply_;
    std::unique_ptr<PlainDatabase> db_;
    ServerConfig server_config_;

    // NOTE: server takes over ownership of db and frees it when it exits.
    // Caller cannot free db
    void set_database(std::unique_ptr<std::vector<uint8_t>> &&db);
};

PIRServer.hpp:可以认为与上面的PlainServer类似,但是方法和类型定义将有所不同和特定。此外,方法将比PlainServer中列出的方法更多。因此,我认为我不能仅使用基类和多态性来消除某些冗余。


TCPServer.hpp :(注意:aio是我所说的boost::asio

class TCPServer {
public:
    explicit TCPServer(aio::io_context &io_context);

private:
    aio::io_context& io_context_;
    tcp::acceptor acceptor_;

    class TCPConnection : public boost::enable_shared_from_this<TCPConnection> {
    public:
        typedef boost::shared_ptr<TCPConnection> pointer;

        static pointer create(aio::io_context& io_context);

        tcp::socket& socket();

        void start();

    private:
        tcp::socket socket_;
        std::string message_;

        explicit TCPConnection(aio::io_context &io_context);

        void handle_read_echo(const boost::system::error_code&, size_t);
        void handle_write_echo(const boost::system::error_code&, size_t);
//        void handle_read_plain(const boost::system::error_code&, size_t);
//        void handle_write_plain(const boost::system::error_code&, size_t);
//    void handle_read_pir(const boost::system::error_code&, size_t);
//    void handle_write_pir(const boost::system::error_code&, size_t);
    };

    void accept_new();
    void handle_accept(
            TCPServer::TCPConnection::pointer& new_connection,
            const boost::system::error_code& error);
};

TCPServer.cpp

TCPServer::TCPServer(aio::io_context& io_context)
        : io_context_(io_context),
          acceptor_(io_context, tcp::endpoint(tcp::v4(), server_config.port)) {

    // Begin listening for incoming connections
    accept_new();
}

void TCPServer::accept_new() {
    // Create a pointer to a new TCPConnection object
    TCPConnection::pointer conn = TCPConnection::create(io_context_);

    acceptor_.async_accept(conn->socket(),
            boost::bind(&TCPServer::handle_accept,
                    this, conn, aio::placeholders::error));
}

void TCPServer::handle_accept(
                    TCPServer::TCPConnection::pointer& conn,
                    const boost::system::error_code& error) {

    std::cout << "[+] New connection: " << conn->socket().local_endpoint()
              << " (local) <---> " << conn->socket().remote_endpoint()
              << " (remote)" << std::endl;

    if (!error) {
        conn->start();
    }

    TCPServer::accept_new();
}


TCPServer::TCPConnection::TCPConnection(aio::io_context &io_context) : socket_(io_context) {}

TCPServer::TCPConnection::pointer TCPServer::TCPConnection::create(aio::io_context& io_context) {
    return pointer(new TCPConnection(io_context));
}

tcp::socket& TCPServer::TCPConnection::socket() {
    return TCPConnection::socket_;
}

void TCPServer::TCPConnection::start() {

    aio::async_read_until(socket_,
                          aio::dynamic_buffer(message_), "\n",
                          boost::bind(&TCPConnection::handle_read_echo,
                                      shared_from_this(),
                                      aio::placeholders::error,
                                      aio::placeholders::bytes_transferred));
}

void TCPServer::TCPConnection::handle_read_echo(const boost::system::error_code& err, size_t) {

    // TODO: error check and guard the user input

    if (!err) {
        // async_write handles serializing the data for the socket
        aio::async_write(socket_,
                         aio::buffer(message_),
                         boost::bind(&TCPConnection::handle_write_echo,
                                     shared_from_this(),
                                     aio::placeholders::error,
                                     aio::placeholders::bytes_transferred));

        message_.clear();
    } else {
        delete this;
    }
}

void TCPServer::TCPConnection::handle_write_echo(const boost::system::error_code& err, size_t) {

    if (!err) {
        aio::async_read_until(socket_,
                              aio::dynamic_buffer(message_),"\n",
                              boost::bind(&TCPConnection::handle_read_echo,
                                          shared_from_this(),
                                          aio::placeholders::error,
                                          aio::placeholders::bytes_transferred));
    } else {
        delete this;
    }

}

因此,基本上,我希望能够根据用户是否输入特定的命令行参数而在TCPServer中调用不同的处理程序,并且这些处理程序应引用在{{1中创建的}}(因为我想通过main()获得db_属性)。我对如何构造它感到很困惑。

在此先感谢您的帮助。

0 个答案:

没有答案