C语言的变量必须先声明后使用。由于数据类型的不同,很多相同的处理得为它们设置不同的副本。例如:
int findMax(int a
, int b
){
return (a
> b
) ? a
: b
;
}
double findMax(double a
, double b
){
return (a
> b
) ? a
: b
;
}
模板的引入就是为了类型的参数化。函数的形参数据类型可变,称为函数模板,实际上代表了一组函数。相似地,类模板的数据成员类型也是可变的。
函数模板:
使用条件:运算相同,只有操作数据类型不同。定义形式:
template<class T1, class T2,...>
{函数体
}
class不可省略;函数体内部涉及具体数据类型时,应用上面自定义的模板参数取代;在template中定义的所有参数都必须出现在函数的形参列表中,原因在于函数模板的工作方式,在使用方法中会讲。
例子:
template<class T>
T
Max(T r1
, T r2
){
T temp
= (r1
> r2
)? r1
: r2
;
return temp
;
}
使用方法:
必须将函数模板中的类型参数实例化才可使用。函数模板实例化是自动的过程,根据实参类型确定。
注意:模板不会对数据类型进行隐式转化。因此C++允许函数模板使用多个模板参数,或者用非模板重载一个同名函数。
template <class T, class D>
T
max(T a
, D b
){
...
}
int max(int a
, int b
){
...
}
在这种情况下就会容易出现二义性问题。先了解函数与函数模板的调用规则:
先查找普通函数,否则;查找函数模板,否则;(隐式)类型转换,这里只能在普通函数中进行;以上都不能实现,或者在第三步中发现有多个函数可以匹配,就会出现错误;
类模板
定义形式:
template <class 模板参数
1, ...>
class className{
...
}
注意:如果类的成员函数在类外定义,必须在每个函数名前面再加上template。
template <class ELEMENT_TYPE>
class List{
ELEMENT_TYPE
* vector
;
int len
;
public:
List(int length
);
...
}
template <class ELEMENT_TYPE>
List
<ELEMENT_TYPE
>::List(int length
){
...
}
类模板实例化形式:(类模板+具体类实例化)
List
<int> int_list
;
以上实例化有两个步骤:
类模板实例化为int型;具体类的实例化,定义一个int型类的实例;
类模板的继承和派生
普通类 -> 类模板 -> 类模板 -> 普通类
在类模板派生类模板时,定义子类要注意传递基类的模板
template <class T>
class Base{
...
}
template <class T1, class T2>
class Base_2 : public Base
<T2
>{
public:
void func(T1
, obj1
, T2 obj2
){
...
}
}
int main(){
Base_2
<char*, double> obj
;
}
类似,在类模板派生普通类时,直接传递具体基类模板类型即可。
class Base_2 : public Base
<double>{
...
}