您的位置:首页 > 编程语言 > C语言/C++

28、C++类模板的特化

2013-04-29 11:50 176 查看

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: