7 模板与泛型编程
面向对象virtual 运行时多态 显示接口
重载、template和泛型 编译期多态 隐式接口
• 条款41:了解隐式接口和编译期多态
Understand implicit interfaces and compile-time polymorphism.
– 通常显示接口由函数的签名式(函数名称、参数类型、返回类型)构成。
– 隐式接口并不基于函数签名式,而是由有效表达式(valid expressions)组成。
– Classes 和 template 都支持接口(interfaces)和多态(polymorphism)。
– 对classes而言接口是显示的(explicit),以函数签名为中心。多态则是通过virtual函数发生于运行期。
– 对template参数而言,接口是隐式的(implicit),奠基于有效表达式。多态则是通过template具现化和函数重载解析(functionoverloading resolution)发生于编译期。
• 条款42:了解typename的双重意义
Understand the two meanings of typename.
– 声明template参数时,不论使用关键字class或typename,意义完全相同。
– 请使用关键字typename标识嵌套从属类型名称;但不得在base class lists(基类列)或member initialization list(成员初始列表)内以它作为Baseclass修饰符。
• 条款43:学习处理模板化基类内的名称
Know how to access names in templatized base classes.
– 可在derivedclass templates 内通过“this->”指向base class templates内的成员名称,或藉由一个明白写出的“base class资格修饰符”完成。
• 条款44:将与参数无关的代码抽离templates
Factor parameter-independent code out of templates.
– Templates 生成多个classes 和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系。
– 因非类型模板参数(non-type template parameters)而造成的代码膨胀,往往可消除,做法是以函数参数或class成员变量替换template参数。
– 因类型参数(typeparameters)而造成的代码膨胀,往往可降低,做法是让带有完全相同二进制表述(binary representations)的具现类型(instantiationtypes)共享实现码。
• 条款45:运用成员函数模板接受所有兼容类型
Use member function templates to accept “all compatible types.”
– 使用memberfunction templates(成员函数模板)生成“可接受所有兼容类型” 的函数。
– 如果你声明 membertemplate 用于“泛化copy构造”或“泛化assignment操作”,你还是需要声明正常的copy构造函数和copy assignment操作符。
– 指针隐式转换:
template<typename T>
class SmartPtr
{
public:
template<typename U>
SmartPtr(const SmartPtr<U>& other):heldPtr(other.get()){ } T* get() const { return heldPtr;} private: T* heldPtr; };
利用基本heldPtr 隐式转换之间自身的约束实现泛化copy构造函数。妙哉。
• 条款46:需要类型转换时请为模板定义非成员函数
Define non-member functions inside templates when type conversionsare desired.
– Template实参推导过程中从不将隐式类型转换函数纳入考虑。(nomember)
– Template class内的friend声明式可以直射某个特定函数。
– 当我们编写一个class template ,而它所提供的“与此template相关的”函数支持“所有参数之隐式类型转换”时,请将那些函数定义为“class template内部的friend函数”。
template<typename T>
class Rational
{
public:
...
friend const Rational<T> operator*(const Rational<T>& lhs,const Rational<T>& rhs)
{
return Rational<T>(lhs.numerator()*rhs.numerator(),lhs.denominator()*rhs.denominator());
}
}
其中友元函数中的<T>模板可以省略。
在一个class template中,template名称可被用来作为" template和其参数 " 的简略表达式。
• 条款47:请使用traitsclasses表现类型信息
– Use traits classes for information about types.
• -------------------------------------------
• 条款48:认识template元编程
Be aware of template metaprogramming.
– Template metaprogramming(TMP,模板元编程)可将工作由运行期移往编译器,因而得以实现早期错误侦测和更高的执行效率。
– TMP可被用来生成“基于政策选择组合”(based on combinations of policy choices)的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码。