- 模板编程/泛型编程:独立于特定类型的编码方式。
函数模板
- 模板声明
template <模板形参表> 函数返回类型 函数(形参表);
模板形参表不能为空
- 模板实例化
函数(实参表)
产生模板特定类型实例的过程成为实例化
调用函数模板与调用函数完全一致。
函数模板不指定模板参数类型,可以通过实参自动推导模板参数类型。
优化
- 把参数值传递改为引用传递,避免类对象默认调用复制构造函数。
- 把函数改成‘inline’内联函数,可以避免函数调用造成的开销
- 模板本质是在编译阶段的替换操作
- 模板形参表不能为空。
- 产生模板特定类型事例的过程称为实例化
- 调用函数模板与调用函数完全一致
- 类模板
- 模板声明
template <模板形参表> class 类名;
- 模板定义
template <模板形参表>
class 类名 {}
- 模板实例化
template <模板实参表> 对象;
- 模板声明
- 模板参数表:多个模板参数之间‘,’分割。
‘模板参数,模板参数、、、’ - 模板参数
- 类型形参
‘class 类型形参’或者‘typename 类型形参’ - 非类型模板参数
‘template <类型 形参>’
- 类型形参
- 非类型模板参数必须是整形外部链接(静态)的指针类型,不能是浮点型、类对象、内部链接(堆、栈)的指针类型
注意:类模板的声明与实现必须放在一个文件内,或者声明文件使用‘#include’方式包含实现文件
类模板的声明与实现是不能够分开写。
模板实例化:具体类型代替模板参数的过程。
- 模板特化:模板实例化后的实体(类、函数)。
- 模板参数推导/推演:由模板实参类型确定模板形参的过程。
类模板参数允许自动类型转换(隐式转换)
函数模板参数不允许自动类型转换(隐式转换)
函数模板实参类型不一致问题 template <typename T> inline const T& Max(const T& a,const T& b){ return a>b?a:b; }
模板实例化时,
Max(2,2.4);
参数推导会出现模板实参类型‘int’与‘double’不一致的错误。
解决方法:
1 . 每个模板参数独立类型template <typename T, typename U> inline const T& Max(const T& a,const U& b){ return a>b?a:b; }
2 . 显示指定模板实参类型
Max<int>(2,2.4)
3 .实参强制类型转换
Max(2,static_cast<int>(2.4));
重载函数模板
1. 非模板函数重载函数模板
函数名相同,参数列表不同。并且函数模板可以实例化出这个非模板函数template <typename T> inline const T& Max(const T& a,const T& b){ return a>b?a:b; }
非模板函数重载
inline int Max(int a,int b){ return a>b?a:b; }
- 调用
Max(1.0,2.0); Max('1',2);
- 说明
- 非模板函数与函数模板实参相同情况下,优先调用非模板函数。
- ‘Max<>’表示强制使用模板
- 非模板函数参数可以隐式转换,函数模板不可以。
函数模板重载
模板函数名相同,参数个数不同
函数模板重载
template <typename T> inline const T& Max(const T& a,const T& b,const T& c){ return Max(a,Max(b,c)); }
Max(1,2,3);
特化
* 指针类型重载函数模板(函数模板重载)template <typename T> inline T const* const& Max(T const* const& a,T const* const b){ return *a>*b?a:b; }
- 字符串指针类型重载函数模板(非函数模板重载)
inline char const* const& Max(char const* const& a,char const){ return strcmp(a,b)> 0?a:b; }
- 整型引用重载函数模板
inline int const& Max(int const& a,int const& b){ return a>b?a:b; }
参数个数不同或者显示指定模板参数
技巧
函数模板参数尽量使用引用类型‘const &’
例如template <typename T> inline const T& Max(const T& a,const T& b){ return a>b?a:b; }
函数模板实例显示指定模板实参可以显示指定模板实参,也可以不指定(类型自动推导),模板实例化必须指定
类模板:不完整的类,一个或者多个成员类型未确定。
函数模板:不完整的函数,一个或者多个参数类型未确定。成员函数:只有调用时才会被实例化。
静态成员:每次类模板实例化,都会被实例化。类实例化成为对象,类模板实例化成类。
- 特化:具体指定类模板的全部模板参数的类型。
- 局部特化:具体指定类模板的部分模板参数的类型
- 类模板特化,每个成员函数必须重新定义
类模板特化,相当于函数模板的重载。