关于函数模板的隐式实例化,显式实例化,显式具体化的学习笔记

在自学函数模板时,对于书上的隐式实例化,显式实例化,显式具体化有一些自己的理解。

对于需要重复使用实现相同功能但传入数据类型不同的函数,可以通过使用函数模板来简化代码量,做到一次声明多次使用。但正是因为C++编译器拥有强大的函数重载和类型识别功能,所以在使用函数时,匹配哪个函数,成了一个较为复杂的问题,而显式实例化,显式具体化正是解决这些问题的一些手段。


函数模板:

template <typename T>

void swap(T &a, T &b) {

T temp = a;
a = b;
b = temp;

}    

以该函数模板为例:

1.隐式实例化:

扫描二维码关注公众号,回复: 11357000 查看本文章

在声明函数模板时,其本身并不会生成函数的定义,它只是一个用于生成函数的方案。当在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时,编译器就会调用优先级更高的显式具体化函数。

猜你喜欢

转载自blog.csdn.net/BrightHao_zi/article/details/80207086