如何拆分Boost.Asio示例C++代码为源文件和头文件以避免引入内部依赖
拆分方案说明
核心采用PIMPL(指向实现的指针)惯用法,将所有内部依赖(Boost.Asio组件、内部连接处理类)完全隐藏在源文件中,对外暴露的头文件仅包含最小公共接口,使用者无需引入任何服务内部依赖头文件。
1. 对外暴露的头文件 tcp_daytime_server.h
该头文件无任何第三方依赖,服务使用者仅需包含此文件即可使用服务:
// tcp_daytime_server.h #ifndef TCP_DAYTIME_SERVER_H #define TCP_DAYTIME_SERVER_H class tcp_server { public: // 构造函数:可自定义监听端口,默认使用daytime服务标准端口13 explicit tcp_server(unsigned short port = 13); ~tcp_server(); // 启动服务,阻塞运行直到程序退出 void run(); private: // 不透明实现指针,内部细节完全隐藏在源文件中 class impl; impl* pimpl_; }; #endif // TCP_DAYTIME_SERVER_H
2. 服务内部实现源文件 tcp_daytime_server.cpp
所有内部逻辑、Boost依赖都放在这个文件中,不对外暴露:
// tcp_daytime_server.cpp #include "tcp_daytime_server.h" #include <ctime> #include <string> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> using boost::asio::ip::tcp; // 内部工具函数 static std::string make_daytime_string() { using namespace std; time_t now = time(0); return ctime(&now); } // 内部连接处理类,完全不对外暴露 class tcp_connection : public boost::enable_shared_from_this<tcp_connection> { public: typedef boost::shared_ptr<tcp_connection> pointer; static pointer create(boost::asio::io_service& io_service) { return pointer(new tcp_connection(io_service)); } tcp::socket& socket() { return socket_; } void start() { message_ = make_daytime_string(); boost::asio::async_write(socket_, boost::asio::buffer(message_), boost::bind(&tcp_connection::handle_write, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } private: tcp_connection(boost::asio::io_service& io_service) : socket_(io_service) { } void handle_write(const boost::system::error_code& /*error*/, size_t /*bytes_transferred*/) { } tcp::socket socket_; std::string message_; }; // tcp_server的实现类 class tcp_server::impl { public: impl(unsigned short port) : acceptor_(io_service_, tcp::endpoint(tcp::v4(), port)) { start_accept(); } void run() { io_service_.run(); } private: void start_accept() { tcp_connection::pointer new_connection = tcp_connection::create(acceptor_.get_io_service()); acceptor_.async_accept(new_connection->socket(), boost::bind(&impl::handle_accept, this, new_connection, boost::asio::placeholders::error)); } void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error) { if (!error) { new_connection->start(); } start_accept(); } boost::asio::io_service io_service_; tcp::acceptor acceptor_; }; // tcp_server对外接口的实现 tcp_server::tcp_server(unsigned short port) : pimpl_(new impl(port)) { } tcp_server::~tcp_server() { delete pimpl_; } void tcp_server::run() { pimpl_->run(); }
3. 使用者示例代码 main.cpp
完全不需要引入Boost头文件,仅包含对外头文件即可使用服务:
// main.cpp #include "tcp_daytime_server.h" #include <iostream> #include <exception> int main() { try { tcp_server server(13); server.run(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0; }
编译说明
- 编译时需链接Boost.System、Boost.Thread库,示例编译命令:
g++ main.cpp tcp_daytime_server.cpp -o daytime_server -lboost_system -lboost_thread - 之前拆分出现模板报错的原因是模板代码的定义必须对实例化点可见,本方案将所有依赖Boost模板的逻辑全部封闭在同一个实现源文件中,避免了跨编译单元的模板实例化问题。
内容的提问来源于stack exchange,提问作者thripper
相关产品推荐
相关产品推荐

