28、C++类模板的特化

来源:互联网 发布:泸州市网络春晚酒文化 编辑:程序博客网 时间:2024/05/31 19:38

C++类模板的特化

有的时候某些类型不能直接用来实例化类模板,或者说直接实例化不能满足需要,

此时就要针对这种类型进行特化,包括特化(即全特化)和偏特化。

1、特化为绝对类型

目的:为了针对特殊的类型进行特殊处理,重新修改成新的逻辑,定义一个

新的特化的类模板。

特点:template后没有形参说明,类模板名加了模板实参列表。

基本语法:

template<>

class  类模板名<模板实参列表>

新的逻辑操作

};

2、偏特化(部分特化)

给出部分实参。仍有个别参数没有给出实际参数。

特点:template后的模板形参的形参没有全部不写,类模板名后添加了参数说明。

或者两个都

基本语法:

template<模板形参列表>

class 类模板名<模板形参表>

};

注:类模板名后的形参,可以把template后的形参当作已知的类型,组合成新

的类型来作为类模板的参数。然后通过实例化template的形参,

最后进一步确定类模板的实参。

注:所有特化类模板之前,一定先需要定义同名的非特化类模板,否则会有编译错误

注:所有特化模板的形参以跟着类模板名后面的 < >为标准,而非特化模板以跟着

template后面的< >为标准。进行参数赋值。

一、全特化

测试程序

#include <iostream>using namespace std;//类模板的特化之全特化//普通非特化类模板template <typename T,int size>class Vector{private :    T   arr_data[size];public:    Vector(T *data)    {        for(int i=0;i<size;i++)        {            arr_data[i] = *(data+i);        }    }    T Sum();};template <typename T,int size>T Vector<T,size>::Sum(){    cout<<"调用非特化类模板实例的Sum函数!"<<endl;    T sumvalue=0;    for(int i=0;i<size;i++)    {        sumvalue+=*(arr_data+i);    }    return sumvalue;}//全特化类模板template <>class Vector<int,1>{private:    int data;public:    Vector(int d);    int Sum();};//全特化的函数在在类外定义,不需要加上 template < >Vector<int,1>::Vector(int d):data(d){}int Vector<int,1>::Sum(){    cout<<"调用全特化类模板Vector<int,1>的函数Sum"<<endl;    return data;}int main(){    int int_arry[10]={1,2,3,4,5,6,7,8,9,10};    float float_arry[10]={2,3,4,5,6,7,8,9,10,11.0};    int i1=100;    Vector<int,10> int_vector(int_arry);    Vector<float ,10> float_vector(float_arry);    Vector<int,1>  int1(i1);    cout<<int_vector.Sum()<<endl;    cout<<float_vector.Sum()<<endl;    cout<<int1.Sum()<<endl;    return 0;}


输出结果:

调用非特化类模板实例的Sum函数!

55

调用非特化类模板实例的Sum函数!

65

调用全特化类模板Vector<int,1>的函数Sum

100

Process returned 0 (0x0)   execution time : 0.130 s

Press any key to continue.

二、部分特化之普通特化

测试程序:

#include <iostream>#include <cstring>using namespace std;//类模板的特化//普通的非特化类模板template <typename T,int size>class Vector{    private:    T arr_data[size];    public:    Vector(T *data )    {        for(int i=0;i<size;i++)        {            arr_data[i]=data[i];        }    }    T   Sum();};template <typename T,int size>T Vector<T,size>::Sum(){    T sumvalue=0;    cout<<"调用非特化类模板实例中的函数!"<<endl;    for(int i=0;i<size;i++)    {        sumvalue+=arr_data[i];    }    return sumvalue;}//这样的求和,如果是针对INT float型都适合,可是针对字符数组就不行。//普通的部分特化template <int size> //只有一个参数被给了实参。class Vector<char ,size>{    private:    char arr_data[size+1];    public:    Vector(char *data )    {        strcpy(arr_data,data);    }    char *  Sum();};template <int size>char * Vector<char,size>::Sum(){    cout<<"调用部分特化类模板Vector<char,size>中的sum函数!"<<endl;    char * c_arry=new char[size+1];    strcpy(c_arry,arr_data);    return c_arry;}int main(){    int int_array[10]={1,2,3,4,5,6,7,8,9,10};    float float_array[10]={2,3,4,5,6,7,8,9,10.0,11.0};    char c_array[10]="ABCDEFG";    const int c_size=sizeof(c_array); //这里如果使用strlen就不可以出现在模板实参中,因为sizeof()编译时处理的。strlen是函数,运行时决定,    //int size 实参要求必须是编译时就能决定出来的常量表达式    Vector<int,10> int_vector(int_array);    Vector<float,10> float_vector(float_array);    Vector<char,c_size> char_vector(c_array);//这里的实例化,也必须是两个参数,    cout<<int_vector.Sum()<<endl;    cout<<float_vector.Sum()<<endl;    cout<<char_vector.Sum()<<endl;    return 0;}


输出结果:

调用非特化类模板实例中的函数!

55

调用非特化类模板实例中的函数!

65

调用部分特化类模板Vector<char,size>中的sum函数!

ABCDEFG

三、部分特化之引用与指针

测试程序:

#include <iostream>using namespace std;//类模板的特化template <typename T,typename U>class Ctest{public:    void f();};template <typename T,typename U>void Ctest<T,U>::f(){    cout<<"调用非特化类模板实例对象的函数"<<endl;}//偏特化为引用template <typename T,typename U>class Ctest<T &,U &>{public:    void f();};template <typename T,typename U>void Ctest<T &,U &>::f(){    cout<<"调用偏特化为引用的类模板实例对象的函数"<<endl;}//偏特化为指针 第二个参数是inttemplate <typename T>class Ctest<T *,int>{public:    void f();};template <typename T>void Ctest<T *,int>::f(){    cout<<"调用偏特化为指针,第二个参数是int的类模板实例对象的函数"<<endl;}int main(){    //只用完全符合特化模板形参的才会调用特化模板,只要不符合的调用的全都是非特化模板。    Ctest<int,int> in_c;    in_c.f();    Ctest<int &,int &> in_c1;    in_c1.f();    Ctest<int *,int &> in_c2;    in_c2.f();    Ctest<int *,int> in_c3;    in_c3.f();    return 0;}


输出结果:

调用非特化类模板实例对象的函数

调用偏特化为引用的类模板实例对象的函数

调用非特化类模板实例对象的函数

调用偏特化为指针,第二个参数是int的类模板实例对象的函数

Process returned 0 (0x0)   execution time : 1.451 s

Press any key to continue.

四、部分特化之类模板

测试程序:

Vector.h

#include <iostream>using namespace std;//类模板的特化之全特化//普通非特化类模板template <typename T,int size>class Vector{private :    T   arr_data[size];public:    Vector(T *data)    {        for(int i=0;i<size;i++)        {            arr_data[i] = *(data+i);        }    }    T Sum();};template <typename T,int size>T Vector<T,size>::Sum(){    cout<<"Vector调用非特化类模板实例的Sum函数!"<<endl;    T sumvalue=0;    for(int i=0;i<size;i++)    {        sumvalue+=*(arr_data+i);    }    return sumvalue;}//全特化类模板template <>class Vector<int,1>{private:    int data;public:    Vector(int d);    int Sum();};//全特化的函数在在类外定义,不需要加上 template < >Vector<int,1>::Vector(int d):data(d){}int Vector<int,1>::Sum(){    cout<<"Vector调用全特化类模板Vector<int,1>的函数Sum"<<endl;    return data;}


main.cpp

#include <iostream>#include "Vector.h"//包含我们自定义的类模板头文件using namespace std;//类模板的特化之特化为另一个类模板template <typename T,int size>class Ctest{public:    void f();};template <typename T,int size>void Ctest<T,size>::f(){    cout<<"Ctest调用非特化类模板实例对象的函数"<<endl;}template <typename T,int size>class Ctest< Vector<T,size>,size>{public:    void f();};template <typename T,int size>void Ctest<Vector<T,size>,size>::f(){    cout<<"Ctest调用特化为Vector类模板的函数"<<endl;}int main(){    //Vector的参数我们并不关心特化和非特化,而由Vector.h文件中的内容决定。    //非特化模板 以跟着template后的< 参数列表> 为标准进行参数赋值    Ctest<int,10> c001;    c001.f();    //特化模板 以跟着类模板名后的< 参数列表> 为标准进行参数赋值    Ctest<Vector<int,10>,10> c002;    c002.f();    return 0;}


输出结果:

Ctest调用非特化类模板实例对象的函数

Ctest调用特化为Vector类模板的函数

Process returned 0 (0x0)   execution time : 1.685 s

Press any key to continue.


原创粉丝点击