7、C++模板函数

函数模板

一、函数模板的定义

基本语法:

template <模板函数参数列表>

返回类型 函数模板名(函数参数列表)

{  函数体  }

注:

1、模板参数列表不可为空,可以是一个或多个类型参数(如:typename 

T1,typename T2),也可以是非类型参数(如: int size),这种非类型参数当

作常量使用,而且在实参化时,需要用一个常量表达式(或常量)赋值。

2、非类型参数,可以在函数体的定义中当作常量使用,也可以当作函数的

默认实参。

3、类型参数可以用该类型声明函数的返回值类型,形参,临时变量

4、非类型的模板 参数的值必须是一个常量,而且是编译时就能确认的常量

包括字面常量、符号常量(const 常量)。

二、函数模板的使用

实例化:在使用函数模板之前,必须先确定模板参数,可由用户明确确指定,也可

由编译器自行推导。

1、实例化化函数模板(生成一个真正意义上的函数)

:根据一组或者更多具体类型或值构造具体的函数

2、取函数模板的地址

:因为函数模板并不是真正的函数,所以其本身没有地址,所以取函数模板的地址

时,也会导致函数模板的实例化。

三、实参推演

:当函数模板被调用时,编译器根据函数的实参决定模板实参的过程。

1、多个函数的实参可以参加同一个模板实参的推演过程,如果模板参数表中

出现多次,则每个推演出来的类型必须是相同的。

2、显示指定函数模板的实参

3、显示声明实例:

template 返回类型 模板名<模板实参列表>(函数形参列表);

注:推演过程中,只要能够将函数实参转换成相应的模板实参即可。

下列3种的类型转换是允许的。

a、左值=右值 

当左值可以做右值使用时,如:指针=数组名。

b、限定符修饰转换

const volatile

:普通的指针变量可以转换为const或volatile指针。

c、到基类的转换

实参:子类对象

模板形参:基类对象。

四、函数模板的特化

同一个模板针对特定数据类型,改变函数体代码逻辑,如数组的求和中 char类型的

处理。

基本语法:

template <>

返回类型 模板名<模板实参列表>(函数参数列表)

{

函数体。

}

注:

1、特化时需要非特化模板函数已经声明过了。

2、template <> 括号不可加原来普通非特化模板函数中的模板形参。

类模板的偏特化。才需要加参数。

函数模板的偏特化严格的来说,函数模板并不支持偏特化,但

由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。

<也可添加模板参数>

五、函数模板的重载

几点要求:

模板名称相同

模板形参相同

函数形参相同(函数返回类型不参与区分)

六、函数模板的编译

:2种编译方式:包含编译方式,

1、包含编译方式

模板在头文件中定义,如果某个源文件需要实例化模板,就包含模板所在的头文件。

2、分离编译方式

头文件是函数模板的声明,模板定义则放在别处的的源文件中,在定义模板的

源文件中,在关键字template前加上export,表示声明一个可导出的函数

模板。在使用该模板函数的文件中包含头文件。

源程序:

#include <iostream>

using namespace std;

//模板函数的定义 ,类型参数和非类型参数

template <typename T,int size>

T min(T (&arr)[size])

{

    T value=arr[0];

    for(int i=0;i<size;i++)

    {

        if(arr[i]<value)

        {

            value=arr[i];

        }

    }

    return value;

}

template float min<float,5>(float (&)[5]);//不能在函数内部

//特化模板 就是指定函数形参的类型,而且需要非特化模板已经在这之前声明。

template <>

char min<char ,10>(char (&arr)[10])

{

    char value=arr[0];

    for(int i=0;arr[i]!='\0';i++)

    {

        if(arr[i]<value)

        {

            value=arr[i];

        }

    }

    return value;

}

template char min</*对应特化模板新添形参列表*/>(char (&arr)[10]);

int main()

{

    int arr[10]={2,4,6,46,2,345,7,9,2,1};

    float farr[5]={12.34,23.5,345.2,45.2,12.0};

    char carr[]="QBCDERTGA";

    const int arrsize=10;

    //使用模板函数时都需要实例化,

    //1、直接调用模板函数,让系统编译程序自动选择进行实参扮演,并实例化,继而调用

    cout<<min(arr)<<endl;

    //2、直接调用模板函数,指定模板实参列表,系统编译程序根据所给模板实参实例化

    cout<<min<int,arrsize/*这里必须是常量表达式*/>(arr)<<endl;

    //3、先显示指定模板函数实参,实例化一个模板函数,也就是真正的实现一个函数,并申请内存空间。

    //同种类型的实参列表,只能实例化一次。见33行

    //使用

    cout<<min(farr)<<endl;

    //使用特化模板,也可以像以上模板一样使用,三种方法

    cout<<min(carr)<<endl;

    return 0;

}

//同样函数模板也可以像一般的函数一样重载:模板名称相同,模板形参相同,函数形参不同。


程序输出结果:

1

1

12

A


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值