一 了解隐式接口和编译器多态:
(1)面向对象:显示接口(explicit interfaces)+运行时多态(runtime polymorphism)。
(2)Templates和泛型编程:主导是隐式接口(implicit interfaces)+编译时多态(compile-time polymorphism);显示接口和运行多态仍然存在。
(3)运行时多态:virtual函数;编译时多态:template实例化(instantiated)和函数重载(funciton overloading)。
二 了解typename的双重含义:
(1)用来声明template参数时,关键字class和typename可互换。
(2)typename还用来标示嵌套从属名称,但不得在base class lists或member initialization list内使用。
*template内出现的名称分为:
*从属名称(dependent names):依赖于某个template参数。
*嵌套从属名称(nested dependent names):从属名称在class内呈嵌套状。
*非从属名称(independent names):不依赖任何template参数。
*例如:
template<typename T>
void show()
{
typename T::const_iterator iter;//嵌套从属名称,必须使用typename标示。
T t;//从属名称
int a;//非从属名称
}
*编译遇到嵌套从属名称,缺省情况下认为嵌套从属名称不是类型(例外:在base class lists和member initialization lists内)。
三 学习处理模块化基类内的名称:
(1)模板 C++拒绝在templatized based classes内寻找继承而来的名称(与object oriented C++不同)。
(2)解决不进入templatized based classes查找名称的三个方法:
*在derived classes内的base class函数调用之前加"this->"。
*使用using表达式:using base<T>::member。
*明白指出被调用的函数位于base classes内。如:base<T>::member()。
四 将与参数无关的代码抽离templates:
(1)因非类型模板实参而造成的代码膨胀,往往可消除,方法:以函数指针或class成员变量替换template参数。
(2)因类型参数而造成的代码膨胀,往往可降低,做法让带有完全相同二进制表述(binary representations)的具现类(instantiation types)共享实现码。
五 运用成员函数模板接受所有兼容类型:
(1)请使用member function templates(成员函数模板)生成“可接受所有兼容类型”的函数。
(2)如果你声明member templates用于“泛化copy构造”或“泛化assignment操作”,那么你还是需声明正常的copy构造函数和copy assignment操作符。因为,member function templates并不改变语言规则。
六 需要类型转换时请为模板定义非成员函数:
(1)当编写一个class templates,而它所提供之“与此template相关的”函数支持“所有参数之隐式类型转换”时,请将那些函数定义为“class template内部的friend函数”。
七 请使用traits classes表现类型信息:
(1)Traits classes使得“类型相关信息”在编译期可用。它们以templates和templates特化完成实现。
(2)整合重载技术后,traits classes可能在编译期对类型进行if...else测试。
八 任何template元编程:
(1)Template metaprogramming 可将工作由运行期转移到编译期,因而得以实现早期错误检测和更高的执行效率。(traits class就是TMP)
(2)TMP可被用来生成“基于政策选择组合”的客户定制代码,也可用来避免生产对某些特殊类型并不适合的代码。