- 什么是类模板?
一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。
如果一个类中数据成员的数据类型不能确定,或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的、实际的类,而是代表着一类类。类模板中的成员函数全部都是模板函数(该说法正确)。
- 什么是模板类
模板类是类模板实例化后的一个产物。可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。
类模板定义及实例化参考
http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html
类模板实例化例子
template <class T>
class My
{
public:
static T cnt;
My()
{
cnt = cnt + 1;
cout << cnt << endl;
}
};
template <class _Type>
_Type My<_Type>::cnt = 0;
int main()
{
My<int> m1; // 1
My<int> m2; // 2
My<int> m3; // 3
My<double> md1; // 1
My<double> md2; // 2
return 0;
}
不同的模板,会实例化出不同的类,是互相不影响的类
模板类中static成员
template <class T>
class My
{
public:
static T cnt;
};
// static 成员必须要在类外重新定义一遍,否则【出现无法识别的标示符错误】
template <class _Type>
_Type My<_Type>::cnt;
int main()
{
My<int>::cnt = 1;
My<double>::cnt = 2.0;
cout << My<int>::cnt << endl; // 1
cout << My<double>::cnt << endl; // 2
return 0;
}
模板使用注意点
- 模板形参的作用范围问题
- 模板参数名字的限制
本来是要使用模板类型的,但是函数里面,将T重新定义成了一个类型,那么T将不再是模板参数类型了
- 多个模板参数声明问题
模板局限性
template < typename T> // 正确声明两个模板参数类型
void cal(const T& a, const T& b)
{
T c = a*b;
cout << c << endl;
}
int main()
{
freopen("in.txt", "r" , stdin);
int a = 1, b = 2;
cal(a, b);
double d1 = 1.1, d2 = 2.2;
cal(d1, d2);
int *p1 = &a;
int *p2 = &b;
cal(p1, p2); // int* 类型
printf("\n");
return 0;
}
模板函数里面的有个乘法,但是乘法不能作用于int*类型。遇到的问题是*模板函数可能无法处理某些类型*,有些时候,模板又是通用的。
解决方案: 运算符重载,为特定类型提供具体的模板定义(模板特化)
模板具体化例子
template < typename T> // 正确声明两个模板参数类型
void cal(T a, T b)
{
T c = a*b;
cout << c << endl;
}
// 具体化一个int*模板函数
template <> void cal<int*>(int* a, int * b)
{
int c = *a * *b;
cout << c << endl;
}
int main()
{
int a = 1, b = 2;
cal(a, b);
double d1 = 1.1, d2 = 2.2;
cal(d1, d2);
int *p1 = &a;
int *p2 = &b;
cal(p1, p2); // int* 类型
printf("\n");
return 0;
}