C++之类模板
关于类模板,有几点值得说明:
1. 类模板必须显式实例化,
2. 类不能重载
类模板的特化
类模板实现特化有几种方式:全特化和半特化(或称偏特化)
假设现在已经实现了一个如下形式的类
template<class T1, class T2>
class Data{
public:Data(){cout << "Data<T1, T2>" << endl;}
private:T1 _d1;T2 _d2;
};template<class T1, class T2>
class Data<T1&, T2*>{
public:Data(){cout << "Data<T1&, T2*>" << endl;}
};
全特化
全特化将会指定所有模板参数,在调用时如果显示实例化的参数列表的类型和全特化后类模板的类型可以一一对应,那么创建的类将是这个唯一的特化后的类对象
template<>
class Data<int, char>{
public:Data(){cout << "Data<int, char>" << endl;}
private:int _d1;char _d2;
};
偏特化
偏特化有两种形式:指定部分模板参数类型 和 将部分或全部参数指定为指针或者引用类型
1. 指定部分模板参数类型
template<class T1>
class Data<T1, char>{
public:Data(){cout << "Data<T1, char>" << endl;}
};
2. 将部分或全部参数指定为指针或者引用类型
template<class T1, class T2>
class Data<T1&, T2*>{
public:Data(){cout << "Data<T1&, T2*>" << endl;}
};
注意:模板的分析一定要配合调用处的情况,
case1: 调用处的参数不是 引用 或者 指针类型
如果参数类型符合特化时声称的参数类型,那么就会调用这个模板
case2: 调用处的参数是 引用 或者 指针类型
如果参数类型符合特化时生成时的类型,而且加上了这个修饰,就会调用这个模板
进一步的说明:
class Data<T1&, T2*> 中 T1& 并不是想要在类中使用T1这个对象时再加一个引用,而只是想要将template<class T1, class T2>中的 这两个类型进行限制,比如传入的是 <Date&, Date*>类型的参数,只需要那么就会调用2. 将部分或全部参数指定为指针或者引用类型中的特化,而且不会对这个类型再加一层引用!
类模板的非类型模板参数
类模板在定义的时候,可以传入一个具体类型的模板参数,并且可以选择固定这个模板参数的初始值,C++中限制了这种可以固定参数初始值的类型只能为整型,指针和引用,这种模板参数称为非类型模板参数,
下面只以整型作为非类型模板参数为例作为说明
template<class T, size_t N = 10>
class array{
public:T& operator[](size_t index){assert(index < N);return _array[index];}const T& operator[](size_t index)const{return _array[index];}size_t size()const{return _size;}bool empty()const{return 0 == _size;}private:T _array[N];size_t _size;
};
对于非类型模板参数的说明,
对于上面的代码,如果在主函数中调用如下两句话
array<int> a1;
array<int, 1000> a2;
编译阶段将会对这两句话分别推导出两个不同的类,然后实例化出不同类型的对象
更多拓展阅读,请见我的C++面试之模板博客 和 模板的通用知识点(挖坑!!!!!)