模板概述
模板(有时称为参数化类型)是用于生成基于类型参数的函数和类的机制。 通过使用模板,您可以设计操作多种类型的数据的单个类或函数,而不必为每种类型创建单独的类。
备注
例如,若要在不使用模板的情况下创建返回两个参数中的最小者的类型安全函数,请编写一组重载函数,如下所示:
// what_are_templates1.cpp
// compile with: /c
// min for ints
int min( int a, int b ) {
return ( a < b ) ? a : b;
}
// min for longs
long min( long a, long b ) {
return ( a < b ) ? a : b;
}
// min for chars
char min( char a, char b ) {
return ( a < b ) ? a : b;
}
通过使用模板,您可以减少对单个函数模板的重复:
// what_are_templates2.cpp
// compile with: /c
template <class T> T min( T a, T b ) {
return ( a < b ) ? a : b;
}
模板可以显著减小源代码的大小并提高代码的灵活性,而不会降低类型安全。
模板有两大类型:函数模板和类模板。 在前面的示例中,min 是函数模板。 类模板是一个带参数的类,例如:
// what_are_templates3.cpp
template <class T> class A {
T m_t;
public:
A(T t): m_t(t) {}
void f(T t);
};
int main() {
A<int> a(10);
}
声明和定义模板在某种程度上类似于其他函数和类,同时存在一些主要差异。 模板声明不完全定义函数或类;它仅定义类或函数的语法主干。 通过称作实例化的过程从模板中创建实际类或函数。 创建的单个类或函数被引用为已实例化的。 例如,类模板:
template <class T> struct A { . . . };
可用于实例化 A<int>、A<char>、A<int*>、A<MyClass*> 等的类。
可以显式或隐式执行类或函数的实例化。 显式实例化是一种对外调用代码中将生成模板的版本的方式。 隐式实例化允许在第一次使用模板的位置根据需要实例化模板。
模板也可以由值参数进行参数化,在这种情况下,声明模板参数的方式与声明函数的参数的方式类似。 禁止将浮点型和类类型作为值参数。
// what_are_templates4.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <int i> class A {
int array[i];
public:
A() { memset(array, 0, i*sizeof(int)); }
};
int main() {
A<10> a;
}
模板的常见问题是,它们可以是通用型解决方案,这意味着同一代码适用于所有类型。 如果需要自定义特定类型的模板的行为,则可以使用专用化。 通过使用显式专用化,模板可专用于特定的实际类型而不是泛型类型。 也可以对类模板进行部分专用化,这在您的模板有多个类型参数且您只想自定义与该模板的部分而非所有参数相关的行为时会很有用。 部分专用化仍为泛型且需要实际模板参数才能生成实际的实例化类。