- 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>{
...
}