zoukankan      html  css  js  c++  java
  • C++—模板(2)类模板与其特化

    我们以顺序表为例来说明,普通顺序表的定义如下:

    1 typedef int DataType;
    2 //typedef char DataType;
    3 class SeqList
    4 {
    5 private :
    6 DataType* _data ;
    7 int _size ;
    8 int _capacity ;
    9 } ;

     模板类也是模板, 必须以 关键字templ ate开头, 后接模板形参表。 模板类一般格式如下:
    template<class 形参名 1, class 形参名 2, . . . class 形参名 n>
    class 类名
    { . . . } ;

     1 // 以模板方式实现动态顺序表
     2 template<typename T>
     3 class SeqList
     4 {
     5 public :
     6 SeqList() ;
     7 ~ SeqList() ;
     8 private :
     9 int _size ;
    10 int _capacity ;
    11 T* _data ;
    12 } ;
    13 template <typename T>
    14 SeqList <T>: : SeqList()
    15 :
    16 _size(0)
    17 , _capacity(10)
    18 , _data(new T[ _capacity] )
    19 {}//注意模板类的类型不是SeqList
    20 template <typename T>
    21 SeqList <T>: : ~ SeqList()
    22 {
    23 delete [] _data ;
    24 }
    25 void test1()
    26 {
    27 SeqList<int > sl1;
    28 SeqList<double > sl2;
    29 }

     

    【 模板类的实例化】
    只 要有一种不同的类型, 编译器就会实例化出一个对应的类。
    SeqList<int > sl1;
    SeqList<double > sl2;
    当定义上述两种类型的顺序表时, 编译器会使用int和double分别代替模板形参, 重新编写SeqList类, 最后创建名 为SeqList<int>和SeqList<double>的类。

    模板参数--实现容器适配器

     1 template <typename T>
     2 class SeqList
     3 {p
     4 rivate :
     5 int _size ;
     6 int _capacity ;
     7 T* _data ;
     8 } ;
     9 // template <class T, class Container>
    10 template <class T, class Container = SeqList<T> > // 缺省参数
    11 class Stack
    12 {
    13 public :
    14 void Push (const T& x) ;
    15 void Pop () ;
    16 const T& Top() ;
    17 bool Empty () ;
    18 private :
    19 Container _con ;
    20 } ;
    21 void Test()
    22 {
    23 Stack<int> s1;
    24 Stack<int , SeqList<int>> s2 ;
    25 // 思考下面这种使用场景会怎样?
    26 Stack<int , SeqList<char>> s3 ;
    27 }

    为了避免上述问题的存在用下面的方法:

    模板的模板参数--容器适配器

     1 template <typename T>
     2 class SeqList
     3 {p
     4 rivate :
     5 int _size ;
     6 int _capacity;
     7 T* _data ;
     8 } ;
     9 // template <class T, template<class> class Container>
    10 template <class T, template<class> class Container = SeqList> // 缺省参数
    11 class Stack
    12 {
    13 public :
    14 void Push(const T& x ) ;
    15 void Pop() ;
    16 const T& Top() ;
    17 bool Empty() ;
    18 private :
    19 Container<T > _con;
    20 } ;
    21 void Test()
    22 {
    23 Stack<int> s1;
    24 Stack<int , SeqList> s2;
    25 }

    非类型的类模板参数

     1 // 静态顺序表
     2 //template<typename T, size_t MAX_SIZE>
     3 template <typename T, size_t MAX_SIZE = 10> //带缺省模板参数
     4 class SeqList
     5 {
     6 public :
     7 SeqList() ;
     8 private :
     9 T _array [MAX_SIZE] ;
    10 int _size ;
    11 } ;
    12 template <typename T, size_t MAX_SIZE>
    13 SeqList <T, MAX_SIZE>: : SeqList()
    14 : _size(0)
    15 {}
    16 void Test()
    17 {
    18 SeqList<int> s1;
    19 SeqList<int , 20> s2;
    20 }

    注意: 浮点数和类对象是不允许作为非类型模板参数的。

    类模板的特化

    类模板的特化:与函数模板类似,当类模板内需要对某些类型进行特别处理时,使用类模板的特化。例如:

     1 // general version
     2 template<class T>
     3 class Compare
     4 {
     5 public:
     6     static bool IsEqual(const T& lh, const T& rh)
     7     {
     8         std::cout <<"in the general class..." <<std::endl;
     9         return lh == rh;
    10     }
    11 };
    12 // specialize for float
    13 template<>
    14 class Compare<float>
    15 {
    16 public:
    17     static bool IsEqual(const float& lh, const float& rh)
    18     {
    19         std::cout <<"in the float special class..." <<std::endl;
    20 
    21         return std::abs(lh - rh) < 10e-3;
    22     }
    23 };
    24 // specialize for double
    25 template<>
    26 class Compare<double>
    27 {
    28 public:
    29     static bool IsEqual(const double& lh, const double& rh)
    30     {
    31         std::cout <<"in the double special class..." <<std::endl;
    32 
    33         return std::abs(lh - rh) < 10e-6;
    34     }
    35 };
    36 int main(void)
    37 {
    38     Compare<int> comp1;
    39     std::cout <<comp1.IsEqual(3, 4) <<std::endl;
    40     std::cout <<comp1.IsEqual(3, 3) <<std::endl;
    41 
    42     Compare<float> comp2;
    43     std::cout <<comp2.IsEqual(3.14, 4.14) <<std::endl;
    44     std::cout <<comp2.IsEqual(3, 3) <<std::endl;
    45 
    46     Compare<double> comp3;
    47     std::cout <<comp3.IsEqual(3.14159, 4.14159) <<std::endl;
    48     std::cout <<comp3.IsEqual(3.14159, 3.14159) <<std::endl;
    49     return 0;
    50 }

    全特化

    还是以顺序表为例说明

     1 全特化
     2 template <typename T>
     3 class SeqList
     4 {
     5 public :
     6 SeqList() ;
     7 ~ SeqList() ;
     8 private :
     9 int _size ;
    10 int _capacity ;
    11 T* _data ;
    12 } ;
    13 template<typename T>
    14 SeqList <T>: : SeqList()
    15 : _size(0)
    16 , _capacity(10)
    17 , _data(new T[ _capacity] )
    18 {
    19 cout<<"SeqList<T>" <<endl;
    20 }
    21 template<typename T>
    22 SeqList <T>: : ~ SeqList()
    23 {
    24 delete[] _data ;
    25 }
    26 template <>
    27 class SeqList <int>
    28 {
    29 public :
    30 SeqList(int capacity) ;
    31 ~ SeqList() ;
    32 private :
    33 int _size ;
    34 int _capacity ;
    35 int* _data ;
    36 } ;
    37 // 特化后定义成员 函数不再需要模板形参
    38 SeqList <int>: : SeqList(int capacity)
    39 : _size(0)
    40 , _capacity(capacity )
    41 , _data(new int[ _capacity] )
    42 {
    43 cout<<"SeqList<int>" <<endl;
    44 }
    45 // 特化后定义成员 函数不再需要模板形参
    46 SeqList <int>: : ~ SeqList()
    47 {
    48 delete[] _data ;
    49 }
    50 void test1 ()
    51 {
    52 SeqList<double > sl2;
    53 SeqList<int > sl1(2) ;
    54 }
     1 偏特化( 局部特化)
     2 template <typename T1, typename T2>
     3 class Data
     4 {
     5 public :
     6 Data() ;
     7 private :
     8 T1 _d1 ;
     9 T2 _d2 ;
    10 } ;
    11 template <typename T1, typename T2>
    12 Data<T1 , T2>: : Data()
    13 {
    14 cout<<"Data<T1, T2>" <<endl;
    15 }
    16 // 局部特化第二个参数
    17 template <typename T1>
    18 class Data <T1, int>
    19 {
    20 public :
    21 Data() ;
    22 private :
    23 T1 _d1 ;
    24 int _d2 ;
    25 } ;
    26 template <typename T1>
    27 Data<T1 , int>: : Data()
    28 {
    29 cout<<"Data<T1, int>" <<endl;
    30 }

    下面的例子可以看出, 偏特化并不仅仅是指特化部分参数, 而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。

     1 // 局部特化两个参数为指针类型
     2 template <typename T1, typename T2>
     3 class Data <T1*, T2*>
     4 {
     5 public :
     6 Data() ;
     7 private :
     8 T1 _d1 ;
     9 T2 _d2 ;
    10 T1* _d3 ;
    11 T2* _d4 ;
    12 } ;
    13 template <typename T1, typename T2>
    14 Data<T1 *, T2*>: : Data()
    15 {
    16 cout<<"Data<T1*, T2*>" <<endl;
    17 }
    18 // 局部特化两个参数为引 用
    19 template <typename T1, typename T2>
    20 class Data <T1&, T2&>
    21 {
    22 public :
    23 Data(const T1& d1, const T2& d2) ;
    24 private :
    25 const T1 & _d1;
    26 const T2 & _d2;
    27 T1* _d3 ;
    28 T2* _d4 ;
    29 } ;
    30 template <typename T1, typename T2>
    31 Data<T1 &, T2&>: : Data(const T1& d1, const T2& d2)
    32 : _d1(d1 )
    33 , _d2(d2 )
    34 {
    35 cout<<"Data<T1&, T2&>" <<endl;
    36 }
    37 void test2 ()
    38 {
    39 Data<double , int> d1;
    40 Data<int , double> d2;
    41 Data<int *, int*> d3;
    42 Data<int&, int&> d4(1, 2) ;
    43 }

    模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。

    关于特化的总结:

    特化的分类

    针对特化的对象不同,分为两类:函数模板的特化类模板的特化

    • 函数模板的特化:当函数模板需要对某些类型进行特化处理,称为函数模板的特化。

    • 类模板的特化:当类模板内需要对某些类型进行特别处理时,使用类模板的特化。

    特化整体上分为全特化偏特化 
    全特化就是模板中模板参数全被指定为确定的类型。全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。

    偏特化就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。

    全特化的标志就是产生出完全确定的东西,而不是还需要在编译期间去搜寻适合的特化实现,貌似在我的这种理解下,全特化的 东西不论是类还是函数都有这样的特点,

    1. 模板函数只能全特化,没有偏特化(重载)。

    2. 模板类是可以全特化和偏特化的。

    很多时候,我们既需要一个模板能应对各种情形,又需要它对于某个特定的类型(比如bool)有着特别的处理,这种情形下特化就是非常必要的。

    模板总结

    【 优点】
    模板复用了 代码, 节省资源, 更快的迭代开发, C++的标准模板库(STL) 因此而产生。
    增强了 代码的灵活性。

    【 缺点】
    模板让代码变得凌乱复杂, 不易维护, 编译代码时间变长。
    出现模板编译错误时, 错误信息非常凌乱, 不易定位错误。




  • 相关阅读:
    VANET
    OTCL,面向对象的脚本一
    NetFPGA-SUME下reference_nic测试
    Mininet-wifi安装和简单使用
    18寒假
    DistBlockNet:A Distributed Blockchains-Based Secure SDN Architecture for IOT Network
    SDVN
    Papers3
    高级软件工程实践总结
    Beta集合
  • 原文地址:https://www.cnblogs.com/33debug/p/6785903.html
Copyright © 2011-2022 走看看