类模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| template<class T> class Stack { private: enum{MAX=10}; T items[MAX]; int top; public: Stack(); bool isempty(); Stack(const Stack& st); Stack& operator=(const Stack& st); }; template<class T> Stack<T>::Stack(){top=0;}
template<class T> bool Stack<T>::isempty(){return top==0;}
template<class T> Stack<T>::Stack(const Stack& st){}
template<class T> Stack<T>& Stack<T>::operator=(const Stack<T> & st){}
|
使用模板类
1 2 3
| Stack<int> a; Stack<string> b;
|
非类型参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| template<class T,int n> class ArrayTp { private: T ar[n]; public: ArrayTp() {}; explicit ArrayTp(const T& v); T& operator[](int i); };
template<class T, int n> ArrayTp<T, n>::ArrayTp(const T& V) { for (int i = 0; i < n; i++) { ar[i] = n; } }
template<class T, int n> T& ArrayTp<T, n>::operator[](int i) { return ar[i]; }
|
- 非类型参数可以是整形、枚举、引用或者指针。
template<class T,double n>
是不合法的,可以是template<class T,double *n>
- 模板代码不能修改非类型参数的值,也不能使用参数的地址。所以不能使用n++或者&n之类的,
- 实例化模板时,非类型参数的值必须是常量表达式
- 每种数组大小都会生成自己的模板
1 2 3
| ArrayTp<double,10> v1; ArrayTp<double,20> v2;
|
使用非类型参数的优缺点:
优点:可以直接使用数组声明即内存栈来维护数组,执行速度偏快
缺点:构造函数法(不使用非类型参数)更通用,因为数组大小是存储在定义中,而不是硬编码,这样可以将不同尺寸的数组进行相互赋值,且也可以动态改变数组的大小
模板多功能性
可以将常规类的技术用于模板类,如模板类可作为基类、作为类型参数等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template<class T> class Array { private: T entry; };
template<class T> class GrowArray::public Array<Type> {};
template<class T> class Stack { Array<T> ar; };
Array<Stack<int>> a;
|
- 递归使用模板
ArrayTp< ArrayTp<int,5>,10> twoTp
≈int twoTp[10][5]
- 使用多个类型参数
1 2 3 4 5 6 7 8
| template<class T1,class T2> class Pair { private: T1 a; T2 b; ... };
|
- 默认类型模板参数
1 2
| template<class T1,class T2=int> class Topp{};
|
注意:可以为类模板类型参数提供默认值,不能为函数模板参数提供默认值。但是函数模板和类模板都可以为非类型参数提供默认值
模板的具体化
- 隐式实例化
1 2 3
| ArrayTp<double,20> * pt; pt = newArray<double ,20>;
|
- 显示实例化
1 2 3
| template class ArrayTp<string,100>;
|
- 显示具体化
1 2 3 4
| template<> class ArrayTp<cosnt char*>{...};
ArrayTp<> a; ArrayTp<const char*> b;
|
- 部分具体化
1 2 3 4 5 6 7
| template<class T1> class Pair<T1,int>{};
Pair<double,double> p1; Pair<double,int> p2; Pair<int,int> p3;
|
为指针提供特殊版本来实现部分具体化
1 2 3 4 5 6 7 8
| template<class T> class Feeb{...}
template<class T*> class Feeb{...}
Feeb<char> fb1; Feeb<char *> fb2;
|
部门具体化可实现各种限制
1 2 3 4 5 6 7 8 9 10
| template<class T1,class T2,class T3> class Trio{};
template<class T1,class T2> class Trio<T1,T2,T2>{};
template<class T1> class Trio<T1,T1*,T1*>{};
Trio<int,short,char*> t1; Trio<int,short> t2; Trio<char,char*,char*> t3;
|
成员模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template<class T> class A { private: template<class V> class B{}; B<T> q; public: A(T t, int i) {}; template<class U> U fun(U u, T t) {return u;} };
A<double> a(3.5, 3); a.fun(10, 2.3);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| template<class T> class A { private: template<class V> class B; B<T> q; public: A(T t, int i) {}; template<class U> U fun(U u, T t); };
template<class T> template<class V> class A<T>::B {};
template<class T> template<class U> U A<T>::fun(U u, T t) { return u; }
template<class T> template<class V>
template<class T,class V>
|
模板作为参数
template <template <typename T> class T2>
模板参数是templateclass T2,其中templateclass是类型,T2是参数。
#定义方式有点类似于非类型参数 template<class T,int n>
1 2 3
| template<template <typename T> class T2,typename U,typename V> class Carb{};
|