一、函数模板
template<typename T1, typename T2>
T1 Add(T1 x, T2 y)
{
return x + y;
}
int main()
{
cout << Add(1, 2) << endl;
cout << Add(3.3, 4.4) << endl;
cout << Add(5, 6.6) << endl;
cout << Add(7.7, 8) << endl;
return 0;
}
上述代码就是一个函数模板,template是定义模板的关键字,其后跟<>,里面使用class或者typename关键字来声明类型名,上述用typename声明了两个类型名,T1和T2;
其下紧跟一个函数,函数的参数、返回值以及函数内部都可以使用模板中声明的类型名。
在接下来调用函数的时候,编译器会根据传入参数的类型,根据模板自动生成一个模板函数,在上述的代码中,共生成了4个Add函数,其形参列表均不相同。
template<typename T1, typename T2>
T1 Add(T1 x, T2 y)
{
return x + y;
}
int Add(int x, int y)
{
return x + y;
}
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
当显示实现了函数模板中的一个函数时,编译器就会先调用已有的函数,而不会根据模板自动生成。
除了编译器自动推演生成模板函数,还可以显示实例化出模板函数。
template<typename T1, typename T2>
T1 Add(T1 x, T2 y)
{
return x + y;
}
int Add(int x, int y)
{
return x + y;
}
int main()
{
cout << Add<double, double>(1, 2) << endl;
return 0;
}
如上述代码所示,在调用Add函数时,显示将类型实例化,编译器就会根据实例化的类型生成一个模板函数。
二、类模板
template<class T>
class Stack
{
private:
T* _a;
size_t _size;
size_t _capacity;
public:
Stack(size_t capacity = 4)
:_capacity(capacity)
, _size(0)
{
_a = new T[_capacity];
}
~Stack()
{
delete[] _a;
_a = nullptr;
_size = _capacity = 0;
}
void Push(const T& x)
{
if (_capacity == _size)
{
T* _tmp = new T[_capacity * 2];
for (size_t i = 0; i < _capacity; ++i)
{
_tmp[i] = _a[i];
}
_capacity *= 2;
delete[] _a;
_a = _tmp;
}
_a[_size++] = x;
}
};
int main()
{
Stack<int> st1;
Stack<double> st2;
st1.Push(1);
st1.Push(2);
st1.Push(3);
st1.Push(4);
st1.Push(5);
st2.Push(1.1);
st2.Push(2.2);
st2.Push(3.3);
st2.Push(4.4);
st2.Push(5.5);
return 0;
}
在上述的类模板中,定义了一个简单的Stack类模板,在使用类模板生成类的时候,一定要显示实例化具体类型。
使用了类模板后,可以让实例化出的Stack对象存储不同类型的数据。
三、特点
模板可以具有非参数类型,可以根据指定的大小动态创建结构;
模板类型无关的,具有很高的复用性;
模板运行时不检查数据类型,也不保证类型安全,只是替换类型;
模板自动推演不支持类型转换,如下:
template<class T>
T Sub(const T& x, const T& y)
{
return x - y;
}
int main()
{
// 错误的代码,自动推演的模板不支持隐式类型转换
// cout << Sub(1, 2.2) << endl;
cout << Sub<int>(1, 2.2) << endl;
return 0;
}
因为Sub模板只有一个T的类型声明,第一个参数1是int类型,因此第二个参数也应该是int类型,如果是其他类型,则会报错;
因此,在参数类型不同时,需要显示指定参数类型;
类模板时一个模具,可以通过模板生成很多模板类,模板类是通过模板实例化出的具体的类。
类模板中的成员函数全部是模板函数。