给网站网站做推广犯法,西宁解封最新通知,企业展厅装修设计,php门户网站源码最近看了The C Programing Language看到了模板的特化#xff0c;突然想起来C Primer上说的显式具体化、隐式具体化、特化、偏特化、具体化等概念弄得头晕脑胀#xff0c;我在网上了找了好多帖子#xff0c;才把概念给理清楚。
看着这么多叫法#xff0c;其…最近看了The C Programing Language看到了模板的特化突然想起来C Primer上说的显式具体化、隐式具体化、特化、偏特化、具体化等概念弄得头晕脑胀我在网上了找了好多帖子才把概念给理清楚。
看着这么多叫法其实就是三种:
显示实例化隐式实例化特化(具体化)、偏特化
一、实例化
1.显示、隐式实例化
什么是实例化一个通过使用具体值替换模板参数从模板产生的普通类函数或者成员函数的过程。
显示实例化通过名字可见就是清楚的表明你要实例化的类型
隐式实例化通过编译器自己推测判断要实例化的类型。
比如一个模板
templateclass T //函数模板实现
void swap(T a, T b)
{T temp;temp a;a b;b temp;
}a. 显示实例化
template void swap(); // 无须给该函数重新编写函数体这只是个声明
为什么要显示实例化
主要是提高效率当显式实例化模板时在使用模板之前编译器根据显式实例化指定的类型生成模板实例这样就相当于本程序里面有个一
void swap(int a, int b)
{int temp;temp a;a b;b temp;
}这样的话每次需要调用 swap(a,b)的时候每次都重新生成该类型的代码可以节省空间也能提高效率。这就是为什么要是显式的实例化的原因。
b. 隐式实例化
隐式实例化指的是在使用模板之前编译器不生成模板的声明和定义实例。只有当使用模板时编译器才根据模板定义生成相应类型的实例。
int i0, j1; swap(i, j); //编译器根据参数ij的类型隐式地生成swap(int a, int b)的函数定义。
隐式实例化就是程序员为了省事把类型省略让编译器判断这是一个偷懒的表现吧。
二、特化
1. 特化(具体化) 然而通常又有一些特殊的情况不能直接使用泛型模板展开实现这时就需要针对某个特殊的类型或者是某一类特殊的类型而实现一个特例模板————即模板特化当T如果为 一个 struct类型的它的交换就无法进行所以我们针对这种特殊的情形我们专门写了一个函数只有当T为 这种struct类型时候才会调用这个特化的函数//对函数
#define MAXNAME 128
struct job
{
char name[MAXNAME]:
int salary;
};templateclass T
void swap(T a, T b )
{T temp;temp a;a b;b temp;
};template void swapint(int a, int b); //显式实例化只需声明template void swapjob(job a, job b) //显式具体化上面已经讲过注意与实例化区分开必须有定义
{int salary:salary a.salary:a.salary b.salary;b.salary salary;
};//explicite specialization.//对类模板
template class T
class Arrary
{
private:T* ar;int l;
...
};//template class declaration.template class Arrayint; //explicit instantiation. 显式实例化template class Arrayjob
{
private:job* ar;int l;
};//expicit specialization. 显式具体化类定义体可以不同于类模板Array2. 偏特化
模板的偏特化是指需要根据模板的部分参数进行特化。
a. 类模板的偏特化 参数 范围 -
b. 函数模板的偏特化 网上看到有人说从严格意义上讲函数模板并不支持偏特化我对这个不是很理解但由于可以对函数进行重载所以可以达到类似于类模板偏特化的效果。
比如 a) template void f(T); 根据重载规则对a)进行重载 b) template class T void f(T*); 如果将a)称为基模板那么b)称为对基模板a)的重载而非对a)的偏特化。 这里我就不深入的剖析偏特化了。
三、模板的匹配顺序
1. 类模板的匹配规则
例如 template class vector{//…//}; // (a) 普通型 template class vector ; // (b) 的显式实例化 template class vectorT*{//…//}; // © 对指针类型特化 template class vector void*{//…//}; // (d) 对void进行特化 每个类型都可以用作普通型(a)的参数但只有指针类型才能用作(b)的参数而只有void才能作为©的参数
所以当一个调用一个模板类首先找显式实例化的如果不匹配接着找特化的然后找偏特化的最后根据模板隐式实例化
2.函数模板的匹配规则
例如
void swap(int a, int b){} // 普通的函数 template swap(int a, int b){} // 特化的模板函数 template void swap(int a, int b); // 显式实例化这个只用声明就行 template void swap(T a, T b){} // 模板
以上书写的顺序就是模板的调用顺序。