模板—类型参数化
前提:在C++程序中,声明变量、函数、对象等实体时,需要指定数据类型,让编译器在程序运行之前进行类型检查并分配内存,以提高程序运行的安全性和效率。但是这种强类型的编程方式往往会导致程序设计者为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码。
定义:模板是一种机制,用于定义数据类型不同但逻辑结构相同的数据对象的通用行为。在模板对象中,运算对象的类型不是实际的数据类型,而是一种参数化的类型
函数模板
例如:定义函数add(),计算两个数之和,可以将类型参数化,如add(T,T),其中,T就是参数化的类型,在调用add()函数时,可以传入任意类型的数据。
这就是函数模板;
定义函数模板的语法格式如下所示:
template<class 类型占位符> //class可以替换成typename
返回值类型 函数名(参数列表)
{
//函数体;
}
template是声明模板的关键字;<>中的参数为模板形参,模板形参不能为空,模板形参和函数形参类似,一个函数模板中可以有多个模板形参
例:
template <class T> //定义函数模板
T add(T t1, T t2)
{
return t1 + t2;
}
int main()
{
cout << add(1, 2) << endl; //传入int类型参数
cout << add(1.2, 3.4) << endl; //传入double类型参数
return 0;
}
函数模板实例化:
用类型参数替代模板中的模板参数,生成具体的函数。
1.隐式实体化:
template <class T> //定义函数模板
T add(T t1,T t2)
{
return t1+t2;
}
2.显示实体化:
template 函数返回值类型 函数名<实例化的类信>(参数列表);
例如:
template<class T>
T add(T t1,T t2){
return t1+t2;
}
template int add<int>(int t1,int t2); //显式实例化为int类型
int main(){
cout<<add<int>(10,'B')<< endl; //函数模板调用
cout<<add(1.2,3.4)<< endl;
return 0;
}
这里显示实例化为int类型,则在调用的时候,不是int类型的会自动转换成int类型进行计算。字符类型的’B’转换成ASCII码值;
3.显示具体化
显式具体化也是基于函数模板的,只不过在函数模板的基础上,添加一个专门针对特定类型的、实现方式不同的具体化函数。
template<>函数返回值类型 函数名<实例化类型>(参数列表)
{
//函数体重新定义
}
例:
template<> void swap<Student>(Student& st1, Student& st2)
{
int temp = st1.id;
st1.id = st2.id;
st2.id = temp;
}
重新定义函数模板只交换结构体的部分数据成员
注意:函数模板可以重载
类模板
类模板是针对成员数据类型不同的类的抽象,它不是一个具体的实际的类,而是一个类型的类,一个类模板可以生成多种具体的类,定义类模板的格式如下所示:
template<class 类型占位符>
class 类名
{
}
定义了类模板后就要使用类模板创建对象以及实现类中的成员函数,这个过程其实也是类模板实例化的过程,实例化出的具体类称为模板类。如果用类模板创建类的对象,例如,用上述定义的类模板A创建对象,则在类模板A后面加上一个< >,并在里面表明相应的类型。
A<int> a;
当有多个模板形参时,创建对象时,类型之间用逗号分隔开;
template<class T1, class T2>
class B
{
public:
T1 a;
T2 b;
T1 func(T1 a, T2& b);
};
B<int,string> b;
使用类模板时,必须要为模板形参显式指定实参
例如:
#include<iostream>
using namespace std;
template< typename T> //类模板
class Array
{
private:
int _size;
T* _ptr;
public:
Array(T arr[], int s);
void show();
};
template< typename T> //类模板外定义其成员函数
Array<T>::Array(T arr[], int s)
{
_ptr = new T[s];
_size = s;
for (int i = 0; i < _size; i++)
{
_ptr[i] = arr[i];
}
}
template< typename T> //类模板外定义其成员函数
void Array<T>::show()
{
for (int i = 0; i < _size; i++)
cout << *(_ptr + i) << " ";
cout << endl;
}
int main()
{
char cArr[] = { 'a', 'b', 'c', 'd', 'e' };
Array<char> a1( cArr, 5); //创建类模板的对象
a1.show();
int iArr[10] = { 1, 2, 3, 4, 5, 6 };
Array<int> a2(iArr, 10);
a2.show();
return 0;
}
注意:类模板在实例化时,带有模板形参的成员函数并不会跟着实例化,这些成员函数只有在被调用时才会被实例化。
如有错误,欢迎在评论区指正。