C++ 最重要的特征之一就是 代码重用。
所以有了这么一个东西,可以
不受数据类型的影响。可以将数据类型也参数化(又叫参数化程序设计)。
于是就产生了了模板。从模板
的字面义来看,有了模板应该就可以自动“产生”一堆类似的东西。
函数模板
比如我们要写最大值的函数,可能要写:
1 | int max(int a, int b){return a > b ? a : b}; |
但是很麻烦,而且加大代码维护难度。
一个替代方案是宏定义,但是宏定义很容易出锅。
因此,C++ 把数据类型也作为一个参数:
1 | template <class T> |
我好了。
这样,对于需要调用 max
函数的任意类,只要定义了类间的 >
符号,即可直接运行。
对于比较 int
和 char
类型的,就不能调用上面的模板了。
其实,还可以以下写:
1 | template <class X, class Y> |
函数模板的匹配
当一个函数有多个模板可以使用的时候,该使用哪个呢?
比如以下代码:
1 | int max(int a, int b){cout << "Template Function Used!\n"; return a > b ? a : b}; |
对于 max(1, 2)
,该调用谁呢?
重载函数的最下匹配遵循以下优先原则:
- 完全匹配时,普通函数优于模板函数;
- 提升转换(如
char
toint
、short
toint
、float
todouble
)- 标准转换(如
int
tochar
、long
todouble
)- 用户定义的类型转换
对于这部分,书上讲的貌似不是特别清楚但是期末了没时间深究了,先挖个坑
类模板
由于 C++ 的 vector
是用类模板实现的,我们从 vector
入手讲讲模板。
定义过程应如下:
1 | template <class T> class vector |
在类外定义 begin()
函数,应为:
1 | //template <模板形参列表> 返回值 类名<模板形参> :: 函数名() |