请选择 进入手机版 | 继续访问电脑版

环信

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: mmap uikit gcc
查看: 368|回复: 4

C++类模板详解

  [复制链接]

42

主题

68

帖子

229

积分

中级会员

Rank: 3Rank: 3

积分
229
发表于 2016-1-27 10:49:21 | 显示全部楼层 |阅读模式

1. 类模板
    提供一种特殊的类以相同的行为处理不同的类型
    在类声明前使用template进行标识
    <typename T>用于说明类中使用的泛指类型 T
    声明的泛指类型 T 可用于声明成员变量和成员函数

    编译器对类模板的处理方式和函数模板相同
        从类模板通过具体类型产生不同的类
        在声明的地方对类模板代码本身进行编译
        在使用的地方对参数替换后的代码进行编译
  1.         template<typename T>
  2.         class Operator
  3.         {
  4.         public:
  5.             T add(T a, T b);
  6.             T minus(T a, T b);
  7.         };
  8.        
  9.         template<typename T>
  10.         T Operator<T>::add(T a, T b)
  11.         {
  12.             return a + b;
  13.         }
  14.        
  15.         template<typename T>
  16.         T Operator<T>::minus(T a, T b)
  17.         {
  18.             return a - b;
  19.         }
  20.        
  21.         int main(int argc, char *argv[])
  22.         {
  23.             Operator<int> op1;
  24.             Operator<double> op2;
  25.             
  26.             cout<<op1.add(5, 4)<<endl;
  27.             cout<<op1.minus(4, 5)<<endl;
  28.             
  29.             cout<<op2.add(1.3, 0.01)<<endl;
  30.             cout<<op2.minus(0.01, 1.3)<<endl;
  31.        
  32.             return 0;
  33.         }       
复制代码
   
    由于类模板的编译机制不同,所以不能像普通类一样分开实现后,在使用时只包含头文件。
    在工程实践上,一般会把类模板的定义直接放到头文件中。
    只有被调用的类模板成员函数才会被编译器生成可执行代码。
   
   
   
2. 类模板特化
    用template<>声明一个类时,表示这是一个特化类。
    当类模板在处理某种特定类型有缺陷时,可以通过类模板的特化来克服处理这种特定类型带来的不足。
    编译器优先选择特化类生成对象。
  1.         template<typename T>
  2.         class Test
  3.         {
  4.         public:
  5.             T test(T v)
  6.             {
  7.                 cout<<"T test(T v)"<<endl;
  8.                 cout<<"sizeof(T) = "<<sizeof(T)<<endl;
  9.                 
  10.                 return v;
  11.             }
  12.         };
  13.        
  14.         template<>
  15.         class Test<int>
  16.         {
  17.         public:
  18.             int test(int v)
  19.             {
  20.                 cout<<"int test(int v)"<<endl;
  21.                 cout<<"sizeof(int) = "<<sizeof(int)<<endl;
  22.                 
  23.                 return v;
  24.             }
  25.         };
  26.        
  27.         class MyTest : public Test<int>
  28.         {
  29.         };
  30.        
  31.         int main(int argc, char *argv[])
  32.         {
  33.             Test<int> t1;
  34.             cout<<t1.test(1)<<endl;
  35.             
  36.             return 0;
  37.         }
复制代码
   

3. 类模板局部特化
    指定类模板的特定实现,并要求某些类型参数仍然必须得模板的用户指定。
    特化可以统一的方式使用类模板和特化类,编译器自动优先选择特化类。
    特化和重新定义新类本质区别:
    如果定义新类,那么将变成一个类模板和一个新类,使用的时候需要考虑究竟是用类模板还是用新类
  1.         template<typename T1, typename T2>
  2.         class Test
  3.         {
  4.         public:
  5.             void add(T1 a, T2 b)
  6.             {
  7.                 cout<<(a + b)<<endl;
  8.             }
  9.         };
  10.        
  11.         /*
  12.         template<typename T>
  13.         class Test<T, T>
  14.         {
  15.         public:
  16.             void add(T a, T b)
  17.             {
  18.                 cout<<"add(T a, T b)"<<endl;
  19.                 cout<<static_cast<T>(a + b)<<endl;
  20.             }
  21.         };
  22.         */
  23.        
  24.         template<typename T>
  25.         class Test<T, int>
  26.         {
  27.         public:
  28.             void add(T a, int b)
  29.             {
  30.                 cout<<"add(T a, int b)"<<endl;
  31.                 cout<<a + b<<endl;
  32.             }
  33.         };
  34.        
  35.         template<typename T1, typename T2>
  36.         class Test<T1*, T2*>
  37.         {
  38.         public:
  39.             void add(T1* a, T2* b)
  40.             {
  41.                 cout<<"add(T1* a, T2* b)"<<endl;
  42.             }
  43.         };
  44.        
  45.         int main(int argc, char *argv[])
  46.         {
  47.             int i = 0;
  48.             int j = 0;
  49.             
  50.             Test<double, int> t; // <T, int>
  51.             Test<long, long> ti; // <T1, T2>
  52.             Test<float, int> tt; // <T, int>
  53.             Test<int*, int*> tp; // <T*, T*>
  54.             
  55.             t.add(10.0001, 8);
  56.             ti.add(2, 3);
  57.             tt.add(4, 5);
  58.             tp.add(&i, &j);
  59.             
  60.             return 0;
  61.         }       
复制代码


4. 非类型模板参数
    函数模板和类模板的模板参数可以是普通数值
    限制:
        变量不能作为模板参数
        浮点数和类对象不能作为模板参数
        全局指针不能作为模板参数
    编译器的推导过程是在编译阶段完成的,推导必须依赖于特化类,否则推导过程无法结束。

  1.         template<typename T, int N>
  2.         void func()
  3.         {
  4.             T array[N] = {0};
  5.             for(int i = 0; i < N; i++)
  6.             {
  7.                 array[i] = i + 1;
  8.                 cout<<array[i]<<" ";
  9.             }
  10.             cout<<endl;
  11.         }
  12.         int main(int argc, char *argv[])
  13.         {
  14.             func<int, 5>();
  15.             func<float, 10>();
  16.             return 0;
  17.         }
复制代码
  1.         template<int N>
  2.         class Sum
  3.         {
  4.         public:
  5.             static const int VALUE = Sum<N - 1>::VALUE + N;
  6.         };
  7.        
  8.         template<>
  9.         class Sum<1>
  10.         {
  11.         public:
  12.             static const int VALUE = 1;
  13.         };
  14.        
  15.         int main(int argc, char *argv[])
  16.         {
  17.             cout<<Sum<10>::VALUE<<endl;
  18.             cout<<Sum<100>::VALUE<<endl;
  19.             return 0;
  20.         }       
复制代码


  • 类模板中可以有一个或多个未指定的泛指类型
  • 可以在需要的特化类模板
  • 特化可以统一的方式使用类模板和新定义的类
  • 特化类总是被编译器优先选择使用
  • 模板的参数可以是普通数值


回复

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2016-1-27 10:50:43 | 显示全部楼层
Array.h
  1. #ifndef _ARRAY_H_
  2. #define _ARRAY_H_

  3. template<typename T>
  4. class Array
  5. {
  6. private:
  7.     int mLength;
  8.     T* mSpace;

  9. public:
  10.     Array(int length);
  11.     Array(const Array& obj);
  12.     int length();
  13.     ~Array();
  14.     T& operator[](int i);
  15.     Array& operator= (const Array& obj);
  16.     bool operator== (const Array& obj);
  17.     bool operator!= (const Array& obj);
  18. };

  19. #endif
复制代码
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2016-1-27 10:51:26 | 显示全部楼层
Array.hpp
  1. #ifndef _ARRAY_DEF_H_
  2. #define _ARRAY_DEF_H_

  3. #include "Array.h"

  4. template<typename T>
  5. Array<T>::Array(int length)
  6. {
  7.     if( length < 0 )
  8.     {
  9.         length = 0;
  10.     }
  11.    
  12.     mLength = length;
  13.     mSpace = new T[mLength];
  14. }

  15. template<typename T>
  16. Array<T>::Array(const Array& obj)
  17. {
  18.     mLength = obj.mLength;
  19.    
  20.     mSpace = new int[mLength];
  21.    
  22.     for(int i=0; i<mLength; i++)
  23.     {
  24.         mSpace[i] = obj.mSpace[i];
  25.     }
  26. }

  27. template<typename T>
  28. int Array<T>::length()
  29. {
  30.     return mLength;
  31. }

  32. template<typename T>
  33. Array<T>::~Array()
  34. {
  35.     mLength = -1;
  36.    
  37.     delete[] mSpace;
  38. }

  39. template<typename T>
  40. T& Array<T>::operator[](int i)
  41. {
  42.     return mSpace[i];
  43. }

  44. template<typename T>
  45. Array<T>& Array<T>::operator= (const Array<T>& obj)
  46. {
  47.     delete[] mSpace;
  48.    
  49.     mLength = obj.mLength;
  50.    
  51.     mSpace = new int[mLength];
  52.    
  53.     for(int i=0; i<mLength; i++)
  54.     {
  55.         mSpace[i] = obj.mSpace[i];
  56.     }
  57.    
  58.     return *this;
  59. }

  60. template<typename T>
  61. bool Array<T>::operator== (const Array<T>& obj)
  62. {
  63.     bool ret = true;
  64.    
  65.     if( mLength == obj.mLength )
  66.     {
  67.         for(int i=0; i<mLength; i++)
  68.         {
  69.             if( mSpace[i] != obj.mSpace[i] )
  70.             {
  71.                 ret = false;
  72.                 break;
  73.             }
  74.         }
  75.     }
  76.     else
  77.     {
  78.         ret = false;
  79.     }
  80.    
  81.     return ret;
  82. }

  83. template<typename T>
  84. bool Array<T>::operator!= (const Array& obj)
  85. {
  86.     return !(*this == obj);
  87. }

  88. #endif
复制代码
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2016-1-27 10:52:33 | 显示全部楼层
main.cpp
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include "Array.hpp"

  4. using namespace std;

  5. int main(int argc, char *argv[])
  6. {
  7.     Array<int> ai(5);
  8.    
  9.     for(int i=0; i<ai.length(); i++)
  10.     {
  11.         ai[i] = i + 1;
  12.     }
  13.    
  14.     for(int i=0; i<ai.length(); i++)
  15.     {
  16.         cout<<ai[i]<<endl;
  17.     }
  18.    
  19.     Array<double> ad(10);
  20.    
  21.     for(int i=0; i<ad.length(); i++)
  22.     {
  23.         ad[i] = (i + 1) / 100.0;
  24.     }
  25.    
  26.     for(int i=0; i<ad.length(); i++)
  27.     {
  28.         cout<<ad[i]<<endl;
  29.     }
  30.    
  31.     return 0;
  32. }
复制代码
回复 支持 反对

使用道具 举报

0

主题

5

帖子

71

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
71
发表于 2016-1-27 10:58:56 | 显示全部楼层

类模板智能指针
  •     通过构造函数接管申请的堆内存
  •     通过析构函数确保堆内存被及时释放
  •     通过重载指针运算符 * 和 -> 模拟指针的行为
  •     通过重载比较运算符 == 和 != 模拟指针的比较

SmartPointer.h
  1. #ifndef _SMARTPOINTER_H_
  2. #define _SMARTPOINTER_H_

  3. template<typename T>
  4. class SmartPointer
  5. {
  6. protected:
  7.     T* m_pointer;
  8. public:
  9.     SmartPointer();
  10.     SmartPointer(const T* pointer);
  11.     ~SmartPointer();
  12.     T* operator->();
  13.     T& operator*();
  14. };

  15. #endif
复制代码

SmartPointer.hpp
  1. #ifndef _SMARTPOINTER_DEF_H_
  2. #define _SMARTPOINTER_DEF_H_

  3. #include "SmartPointer.h"

  4. template<typename T>
  5. SmartPointer<T>::SmartPointer()
  6. {
  7.     m_pointer = NULL;
  8. }

  9. template<typename T>
  10. SmartPointer<T>::SmartPointer(const T* pointer)
  11. {
  12.     m_pointer = const_cast<T*>(pointer);
  13. }

  14. template<typename T>
  15. SmartPointer<T>::~SmartPointer()
  16. {
  17.     delete m_pointer;
  18. }

  19. template<typename T>
  20. T* SmartPointer<T>::operator->()
  21. {
  22.     return m_pointer;
  23. }

  24. template<typename T>
  25. T& SmartPointer<T>::operator*()
  26. {
  27.     return *m_pointer;   
  28. }   

  29. #endif
复制代码

main.cpp
  1. #include "SmartPointer.hpp"

  2. using namespace std;

  3. class Test
  4. {
  5. public:
  6.     int i;
  7.     void print()
  8.     {
  9.         cout<<i<<endl;
  10.     }
  11. };

  12. int main(int argc, char *argv[])
  13. {
  14.     SmartPointer<int> pi = new int(5);
  15.     SmartPointer<Test> pt = new Test();
  16.    
  17.     cout<<*pi<<endl;
  18.    
  19.     *pi = 10;
  20.    
  21.     cout<<*pi<<endl;
  22.    
  23.     pt->i = 20;
  24.     pt->print();
  25.    
  26.     return 0;
  27. }
复制代码




回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|环信 Glofty.com ( 粤ICP备15084637号 )

GMT+8, 2017-4-27 22:56 , Processed in 0.246434 second(s), 21 queries .

快速回复 返回顶部 返回列表