目录
条款44:将与参数无关的代码抽离template(需要靠经验,将相同的部分抽离出来)
条款41:了解隐式接口和编译期多态
class和template都是支持接口和多态的
首先需要认识到在class中我们使用的是显式接口和运行期多态,所谓显式接口就是在源码中可以明确可见的接口,运行期多态则是在运行期根据引用或指针指向的实际类型决定调用哪个函数。
显示接口是由函数的签名式(也就是函数名称、参数类型、返回类型)构成,运行期多态是依靠virtual函数在运行期发生
在template中使用的则是隐式接口和编译期多态
隐式接口并不基于函数签名式而是有效表达式(即模板实际元素所需要的接口是根据模板中实际调用了元素接口的表达式来确定的),编译期多态是通过template具现化和函数重载解析发生于编译期(类似于哪个函数需要被重载)
条款42:了解typename的双重意义
当用于声明template参数时,前缀关键字class和typename作用完全一样,也就是template<class T>和template<typename T>可以互换
但是当我们要调用关键字typename标识嵌套从属类型名称时(也就是使用模板类型T中定义的类型时)需要在前面加上关键字typename。
注意不能在派生列表和初始化列表中作为base class的修饰词
例:template<typename _Ty>
struct remove_reference<_Ty&>
{
using type = _Ty;
}
如果想获得type的类型就需要加上typename声明
template<class_Ty>
using remove_reference_t = typename remove_reference<_Ty&>::type
或者是要想获得模板参数T中声明的类型也需要加上typename
条款43:学习处理模板化基类内的名称
注意使用template的同时也可以使用继承,但是如果直接使用的话会出现无法调用基类中成员和接口的问题,因为模板除了通用版本还有全特化版本而全特化版本中很有可能不含有通用模板中具有的接口(甚至可能和通用版本完全不同),编译器会默认屏蔽基类所有接口,解决这一问题推荐两种做法:1.通过this->来指向要调用的基类成员和接口 2.通过using声明式告诉编译器存在这一个函数 3.明确指出要调用的函数的作用域为base class(效果最差因为无法使用多态)
条款44:将与参数无关的代码抽离template(需要靠经验,将相同的部分抽离出来)
Template生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系(只有少量参数不同的重复的二进制代码)