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.