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