28、C++类模板的特化

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;

}

//偏特化为指针 第二个参数是int

template <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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 函数模板特化是指为特定的数据类型或者特定的函数参数提供特殊的实现。这样可以在处理某些特殊情况时,使用不同的实现逻辑,以满足特定的需求。 函数模板特化的语法如下: ```cpp template <> return_type function_name<specific_type>(parameters) { // 实现特化的代码 } ``` 其中,`template <>` 表示这是一个函数模板的特化版本,`specific_type` 是要特化的数据类型,`function_name` 是要特化的函数名,`parameters` 是函数的参数列表,`return_type` 是函数的返回类型。 举个例子,设我们有一个通用的函数模板用于计算两个数相加: ```cpp template <typename T> T add(T a, T b) { return a + b; } ``` 如果我们想要为 `int` 类型提供一个特化版本,实现乘法运算而不是加法运算,可以这样写: ```cpp template <> int add<int>(int a, int b) { return a * b; } ``` 这样,在使用 `add` 函数模板时,如果参数是 `int` 类型,就会自动选择特化版本进行计算。 需要注意的是,函数模板特化是根据数据类型进行匹配的,而不是根据参数数量或者参数类型进行匹配。因此,在进行函数模板特化时,要确保特化版本与通用版本的参数类型和数量完全一致,否则可能会导致编译错误。 另外,还可以进行部分特化,即只特化其中一部分参数类型。部分特化的语法与完全特化类似,只是在模板参数列表中指定部分参数类型即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值