28、C++类模板的特化

本文详细介绍了C++中的类模板特化概念,包括全特化和偏特化,并通过多个实例展示了如何针对特定类型进行特化处理,以便更好地理解和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.


<think>嗯,用户想了解C++类模板特化的使用方法和示例。根据他们提供的引用内容,我需要先理解类模板特化的基本概念和应用场景。类模板特化通常用于针对特定型提供不同的实现,比如当通用模板无法正确处理某些型时,比如指针型。 首先,我应该回顾引用中的例子。引用[1]提到了对Date*指针型的特化,通过特化Less类模板来正确比较指针指向的对象。这说明特化允许我们为特定型定制行为。引用[2]中的例子展示了函数模板在处理指针时可能得到错误结果,这解释了为什么需要特化类模板特化可以解决似问题,但用户的问题是关于类模板特化的,所以需要集中讨论的情况。 接下来,我需要确定如何分步骤解释类模板特化的使用方法。可能的结构包括定义、使用场景、语法格式、示例代码以及注意事项。用户可能需要看到具体的代码示例来理解如何实现特化,比如全特化和偏特化的区别。 全特化是指所有模板参数都指定为具体型的情况,而偏特化(引用中可能称为部分特化)则是部分指定参数,或者对参数进行某种模式匹配,比如针对指针型的通用处理。例如,引用[4]提到模板特化分为函数和,这里重点在类模板。 需要确保示例代码正确,比如在类模板特化时使用template<>语法,并在结构体或名后指定特化参数。同时,注意特化的成员函数或操作符的实现是否覆盖了通用模板的不足。 另外,用户可能想知道何时使用特化,比如处理指针、特定型或优化特定情况下的性能。例如,处理字符串时的特化,或者对某些算法进行优化,如引用中的比较操作符。 还要注意区分函数模板特化类模板特化的不同写法,如引用[1]中提到的小贴士。这可能是一个容易出错的地方,需要明确指出类模板特化的语法结构。 最后,生成相关问题需要考虑用户可能的后续疑问,比如特化与继承的关系、与模板元编程的联系,或者实际应用中的案例。例如,标准库中的类模板特化应用,如std::vector<bool>的特化。</think>### C++类模板特化的使用方法及示例 #### 一、类模板特化的定义 类模板特化是针对特定型或条件,为类模板提供定制化实现的技术。当通用模板无法满足某些特殊型的需求时(例如指针型、特定型),通过特化可以覆盖默认行为[^2][^4]。 --- #### 二、使用场景 1. **处理指针型**:通用模板可能错误比较指针地址而非实际值[^2] 2. **优化性能**:针对特定型设计更高效的实现 3. **特殊型处理**:如字符串、自定义需要特殊逻辑 --- #### 三、语法格式 1. **全特化**:指定所有模板参数 ```cpp template <> class ClassName<SpecificType> { // 特化实现 }; ``` 2. **偏特化(部分特化)**:指定部分参数或添加限制条件 ```cpp template <typename T> class ClassName<T*> { // 针对所有指针型的特化 // 实现 }; ``` --- #### 四、具体示例 ##### 示例1:指针型全特化 ```cpp // 通用模板 template <typename T> struct Comparator { bool operator()(const T& a, const T& b) { return a < b; } }; // 全特化:处理Date型指针 template <> struct Comparator<Date*> { bool operator()(Date* a, Date* b) { return *a < *b; // 比较对象值而非指针地址 } }; ``` *用途:比较`Date*`时自动解引用[^1]* --- ##### 示例2:偏特化处理指针型 ```cpp // 通用模板 template <typename T> class Vector { // 通用实现 }; // 偏特化:所有指针型 template <typename T> class Vector<T*> { // 优化指针存储的特殊实现 }; ``` *特点:适用于任何指针型(如`int*`, `string*`等)[^4]* --- ##### 示例3:型限制特化 ```cpp // 通用模板 template <typename T> struct TypeInfo { static const char* name() { return "unknown"; } }; // 特化字符串型 template <> struct TypeInfo<std::string> { static const char* name() { return "string"; } }; ``` *测试使用:* ```cpp cout << TypeInfo<int>::name(); // 输出 unknown cout << TypeInfo<string>::name(); // 输出 string ``` --- #### 五、注意事项 1. **特化顺序**:先声明通用模板,再写特化版本 2. **成员一致性**:特化类模板需要重新实现所有必要成员 3. **编译检查**:特化版本必须出现在通用模板之后 4. **与继承区别**:特化是模板级定制,而非继承关系[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值