类模板

(1)要注意什么时候使用类名,什么时候使用类的类型

例如:

  1. #include <vector>
  2. #include<stdexcept>
  3. template<typename T>
  4. class Stack{
  5. private:
  6.     std::vector<T> elems;
  7. public:
  8.     void push(T  const&);
  9.     void  pop();
  10.     T top() const;
  11.     bool empty() const{
  12.         return elems.empty();
  13.     }
  14. };
  15. template<typename T>
  16. void Stack<T>::push(T const& elem)
  17. {
  18.     elems.push_back(elem);
  19. }
  20. template<typename T>
  21. void Stack<T>::pop(){
  22.     if(elems.empty()){
  23.         throw std::out_of_range("Stack<T>::pop():  empty elems");
  24.     }
  25.     elems.pop_back();
  26. }
  27. template<typename T>
  28. T Stack<T>::top() const{
  29.     if(elems.empty()){
  30.         throw std::out_of_range("Stack<T>::pop():  empty elems");
  31.     }
  32.     return elems.back();
  33. }

当实现自己的构造函数、析构函数时,应该使用类名,而在实现自己的拷贝构造函数和赋值函数时应使用类型:

如:

  1. template <typenaem T>
  2. class Stack{
  3.   private:
  4.       ....
  5.       Stack(Stack<T> const&);
  6.       Stack<T>&  operator=(Stack<T> const&);
  7.       ....
  8. };

拷贝构造函数中的参数是类型,所以使用了Stack<T>表示。

 

(2)成员函数的实现:

  1. template<typename T>
  2. void Stack<T>::push(T const& elem)
  3. {
  4.     elems.push_back(elem);
  5. }

为了定义一个类模板的成员函数,必须指定该成员函数是一个模板函数,而且还要使用这个类模板的完整类型限定符。如

Stack<T>.

 

(3)类模板的使用

   注意,只有那些被调用的成员函数,才能产生函数的实例化代码。对与类模板,成员函数只有在被使用的时候才会被实例化。这样可以节省空间和时间;另一个好处就是:对于那些“未能提供所有成员函数中所有操作的”类型,你也可以使用该类型来实例化类模板,只要对那些“未能提供某些操作的”成员函数,模板内部不使用即可。

 

 

 

(4)类模板的特化

        通过特化类模板,我们可以优化基于某种特定类型的实现,或者克服某种特定类型在实例化类模板时所出现的不足。另外,如果要特化一个类模板,你还要特化该类模板的所有成员函数。虽然也可以只特化某个成员函数,但是这个做法并没有特化整个类,也就没有特化整个类模板。

      为了特化一个类模板,你必须在起始处声明一个template<>,接下来声明用来特化类模板的类型。这个类型被用作模板实参,且必须在类名的后面直接指定:

  1. template<>
  2. class Stack<std::string>{
  3. .......
  4. }

 

   进行类模板的特化时,每个成员函数都必须重新定义为普通函数,原来模板函数中的每个T也应被进行特化的类型取代:

  1. void Stack<std::string>::push(std::string const& elem)
  2. {
  3.    elems.push_back(elem);
  4. }

(5)局部特化

        类模板可以被局部特化。我们可以在特定的环境下指定类模板的特定实现,并且要求某些模板参数仍然必须由用户来定义。例如类模板:

  1. template<typename T1,typename T2>
  2. class MyClass{
  3. .....
  4. };

可以有以下几种局部特化:

 

  1. template<typename T>
  2. class MyClass<T,T>{
  3. .....
  4. };
  5. template<typename T>
  6. class MyClass<T,int>{//第二个模板参数的类型是int
  7. .....
  8. };

但是要注意其中有可能产生的二义性。

 

(6)缺省模板实参

 对于类模板,你还可以为模板参数定义缺省值;这些值就被称为缺省模板参数;而且,它们还可以引用之前的模板参数。例如,在类Stack<>中,你可以把用于管理元素的容器定义为第2个模板参数,并且使用std::vector<>作为它的缺省值:

  1. #include<vector>
  2. #include<stdexcept>
  3. template <typename T, typename Cont=std::vector<T>  >
  4. class Stack{
  5. private:
  6.     Cont elems;
  7. public:
  8.     void push(T  const&);
  9.     void pop();
  10.     T top() const;
  11.     bool empty() const{
  12.         return elems.empty();
  13.     }
  14. };
  15. template <typename T,typename Cont>
  16. void  Stack<T ,Cont>::push(T const& elem)
  17. {
  18.     elems.push_back(elem);
  19. }
  20. template<typename T,typename Cont>
  21. void Stack<T,Cont>::pop()
  22. {
  23.     if(elems.empty()){
  24.         throw std::out_of_range("Stack<>::pop(): empty stack");
  25.     }
  26.     elems.pop_back();
  27. };
  28. template<typename T,typename Cont>
  29. T Stack<T,Cont>::top() const{
  30.     if(elems.empty()){
  31.         throw std::out_of_range("Stack<>::top():empty stack");
  32.     }
  33.     return elems.back();
  34. }
  35. #include<iostream>
  36. #include<deque>
  37. #include <cstdlib>
  38. #include "stack3.h"
  39. int main()
  40. {
  41.     try
  42.     {
  43.         Stack<int>  intStack;
  44.         Stack<double,std::deque<double>  >dblStack;
  45.         intStack.push(7);
  46.         std::cout<<intStack.top()<<std::endl;
  47.         intStack.pop();
  48.         dblStack.push(42.42);
  49.         std::cout<<dblStack.top()<<std::endl;
  50.         dblStack.pop();
  51.         dblStack.pop();
  52.     }
  53.     catch (std::exception const& ex)
  54.     {
  55.         std::cerr <<"Exception:"<<ex.what()<<std::endl;
  56.         return EXIT_FAILURE;
  57.     }
  58. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值