1.类模板Stack的实现
类模板的声明和函数模板的声明相似,下面是一个类模板Stack的例子,这个类的类型是Stack
- 和普通类的声明相似,先在类声明前加一行template
,然后将类声明中的数据类型换成虚拟类型参数T。
- 类模板的成员函数在类模板外定义时必须指定成函数模板,且需要使用这个类模板的完整类型限定符Stack
::。
1 | #include <vector> |
2.类模板Stack的使用
类模板定义对象时形式为:类模板名<实际类型> 对象名或类模板名<实际类型> 对象名(实参表列)。例如,Stack
1 | Stack<int> intStack; //元素类型为int的栈 |
同时,模板实参可以为任何类型:
1 | Stack<float*> floatStrStack; //元素为浮点型指针的栈 |
注意,两个靠在一起的模板尖括号(即>) 之间要留一个空格;否则,编译器会误认为你在使用operator>>,从而导致语法错误。
3.类模板的特化
因为类模板中的定义不一定适用于所有数据类型,所以针对此类型应该重新定义,即所谓类模板的特化。如果要特化一个类模板,自然要特化此类模板所有的成员函数。
3.1.全特化
特化的类上面应该加着templlate<>,并且特化后的类的类型应该将T换成具体的数据类型,比如int,string等。同时,每个成员函数都必须重新定义为普通函数。下面是一个用std::string特化Stack<>的完整例子。
1 | #include <deque> |
上面的例子中用deque而不是vector,说明:特化的实现可以和基本类模板的实现完全不同。
3.2.局部特化
可以在特定的情况下指定类模板的特定实现,并且部分模板参数依然必须有用户来定义。例如类模板:
1 | template <typename T1, typename T2> |
可以有以下几种局部特化:
1 | //1.局部特化:两个模板参数具有相同的类型 |
下面的例子展示各种声明会使用哪个模板:
1 | MyClass<int,float> mif; //使用MyClass<T1,T2> |
如果有多个局部特化同等程度地匹配某个声明,那么该声明就具有二义性:
1 | MyClass<int,int> m; //ERROR:同时匹配MyClass<T,T>和MyClass<T,int> |
为了解决例子2中二义性,你可以另外提供一个指向相同类型指针的特化:
1 | template <typename T> |
4.缺省模板实参
我们上面例子中的类模板Stack<>是通过C++标准库的vector<>来实现的;因此,我们不需要亲自实现内存管理、拷贝构造函数和赋值运算符。同时,类模板还可以为模板参数定义缺省值,这些值称为缺省模板实参。
1 | #include <vector> |
可以看到,上面的类模板有两个模板参数,因此每个成员函数的定义都必须具有这两个参数。我们仍然可以像前面的例子使用这个栈,就是说只传递第一个类型实参给这个类模板,将会利用vector来管理stack的元素。使用方式如下:
1 | //int栈 |
参考:
《C++Templates》