假设您有一个班级,他们的工作就是连接到远程服务器.我想抽象这个类来提供两个版本,一个通过UDP连接,另一个通过TCP连接.我想构建最精简的运行时代码,而不是使用多态,我正在考虑模板.这是我想象的,但我不确定这是最好的方法:
class udp {}; class tcp {}; templateclass service { private: // Make this private so this non specialized version can't be used service(); }; template class service { private: udp _udp; X _x; }; template class service { private: tcp _tcp; X _x; };
因此最终的好处是T的通用性仍然可用,但设置UDP或TCP连接所需的非常不同的代码已经过专门化.我想你可以将它们放在一个类中,或者提供另一个类,它遵循一些纯虚拟接口来设置网络连接,比如IConnectionManager.
但这确实留下了通用T的代码问题,现在必须在两个专用版本中编写和维护,它们最终都是相同的.如何最好地解决这个问题?我有一种感觉,我认为这一切都错了.
最好使用传输协议的策略来完成此操作:
templateclass service : Transport { public: typedef Transport transport_type; // common code void do_something() { this->send(....); } }; class tcp { public: void send(....) { } }; class udp { public: void send(....) { } }; typedef service service_tcp; typedef service service_udp;
请注意,这也是多态的.它被称为编译时多态.将策略放入基类将受益于Empty-Base-Class-Optimization.也就是说,您的基类不需要占用任何空间.将策略作为成员具有另一个缺点,即您总是必须将内容委托给该成员,这可能会随着时间的推移而变得烦人." Modern C++ Design "一书深入描述了这种模式.
理想情况下,传输协议不需要知道有关它上面的协议的任何信息.但是如果由于某种原因你必须得到一些关于它的信息,你可以使用crtp模式wiki:
template class Transport> class service : Transport{ // since we derive privately, make the transport layer a friend of us, // so that it can cast its this pointer down to us. friend class Transport ; public: typedef Transport transport_type; // common code void do_something() { this->send(....); } }; template class tcp { public: void send(....) { } }; template class udp { public: void send(....) { } }; typedef service service_tcp; typedef service service_udp;
您不必将模板放入标题中.如果明确地实例化它们,您将获得更快的编译时间,因为必须包含更少的代码.把它放到service.cpp中:
template class service; template class service ;
现在,使用服务的代码不需要知道模板的服务代码,因为该代码已经生成到service.cpp的目标文件中.