概述
在自学函数模板时,对于书上的隐式实例化,显式实例化,显式具体化有一些自己的理解。
对于需要重复使用实现相同功能但传入数据类型不同的函数,可以通过使用函数模板来简化代码量,做到一次声明多次使用。但正是因为C++编译器拥有强大的函数重载和类型识别功能,所以在使用函数时,匹配哪个函数,成了一个较为复杂的问题,而显式实例化,显式具体化正是解决这些问题的一些手段。
函数模板:
template <typename T>
void swap(T &a, T &b) {
T temp = a;a = b;
b = temp;
}
以该函数模板为例:
1.隐式实例化:
在声明函数模板时,其本身并不会生成函数的定义,它只是一个用于生成函数的方案。当在main函数里调用函数模板时,编译器会根据传入的实参类型确定T的值,从而生成swap的一个实例,该实例是一个函数定义,此过程称为隐式实例化。
2.显式实例化:
以生成int类型的实例为例:
语法:template void swap <int> (int &, int &);
这意味着可以直接命令编译器创建特定的实例 如swap <int> ( )
相比于隐式实例化,运用显式实例化可使匹配该函数有更高的优先级,并且可进行强制类型转换。
用一个具体的例子来帮助理解
......
template <typename T>
void return_value(T a, T b) {
return a;}
void return_value(int a,int b){
return b;
}
int main()
{
double a=1.0;
double b=2.0;
int c=1;
int d=2;
return_value<int>(c,d); //①
return_value<int>(a,b); //②
}
(1)因为非模板函数拥有更高的优先级,这就意味着对于①,若不进行显式实例化,编译器将优先调用非模板函数,即return_value(c,d),返回d;加上<int>进行显式实例化之后,调用模板函数,返回c。
(2)对于调用②,若不进行显式实例化,由于传入实参为double类型,则编译器将模板隐式实例化为void return_value(double a,double b);,而加上<int>进行显式之后,将会实例化为void return_value(int a,int b); 进行强制类型转换。
3.显式具体化:
声明一个关于学生信息的结构体:
struct student{
char name[10];
int id;
double grade;
}
在main函数中得到两个同学的信息:
int main(){
student a={1,"Tom",80};
student b={2,"Lucy",90};
}
如果你想讲变量a,b中存储的学生信息交换,则可调用swap(a,b);此时T被看做struct student类型。
但是,如果你想只交换id和name,并不交换成绩呢?
你或许想使用函数重载重写swap函数
void swap(T &a,T&b){
int temp=a.id;
a.id=b.id;
b.id=temp;
char* temp=a.name;
a.name=b.name;
b.name=temp;
}
但实际上,C++编译器不根据函数内容确定函数,而是根据形参列表,因此重载的函数与原函数是冲突的,此时会编译器会报错,这时就需要用到现实具体化。
template <> swap<student>(student &a,student &b){
int temp=a.id;
a.id=b.id;
b.id=temp;
char* temp=a.name;
a.name=b.name;
b.name=temp;
}
而后,当你传入a b时,编译器就会调用优先级更高的显式具体化函数。
最后
以上就是怕孤单春天为你收集整理的关于函数模板的隐式实例化,显式实例化,显式具体化的学习笔记的全部内容,希望文章能够帮你解决关于函数模板的隐式实例化,显式实例化,显式具体化的学习笔记所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复