一、为什么使用函数模板

假设我们在程序中需要比较两个变量的大小,但变量的类型可能是int、float或者double,此时为了满足程序的要求我们可能会在程序中编写多个函数,如:

 //比较两个int型变量的大小
int compare(const int &a,const int &b){
return a>b?a:b;
}
//比较两个float型变量的大小
float compare(const float &a,const float &b){
return a>b?a:b;
}
//比较两个double型变量的大小
double compare(const double &a,const double &b){
return a>b?a:b;
}

在上面的代码中,我们发现编写的函数除了函数参数类型和返回值类型不同之外其余完全相同,这样导致的结果就是该程序代码的冗余性较高。为了解决这个问题,我们可以使用函数模板来编写与类型无关的函数以降低程序的冗余性

二、什么是函数模板

一个函数模板就是一个公式,可用来生成针对特定类型的函数体

语法:

template <typename 形参名,typename 形参名,......>
返回值类型 函数名(参数列表){
/*..........
函数体
...........*/
}

实例演示:

 //compare函数的函数模板
template <typename type>
type compare(const type &a,const type &b){
return a>b?a:b;
}

 特别注意:

1.在函数模板的定义中,模板参数列表不能为空

2.在进行模板定义的时候可以用关键字class代替关键字typename,二者在这里是等价的。甚至可以在定义函数模板时同时使用这两个关键字,但还是推荐使用typename,因为这样会使程序的可读性更好

 template <typename type1,class type2>
void func(type1 a,type2 b){
cout<<a<<endl;
cout<<b<<endl;
}

3.模板参数(<>包裹的参数)表示在函数定义中使用到的类型或值。当使用模板时,我们(隐式地或显式地)指定模板实参,将其绑定到模板参数上

4.inline和constexpr的函数模板:将关键字inline或constexpr放在模板参数之后,返回值类型之前即可

 //inline函数的函数模板
template <typename type>
inline type func(type a){
a+=;
return a;
}

三、函数模板的实例化

当我们调用一个函数模板时,编译器(通常)用函数实参来为我们推断模板实参,例如上面的compare函数,编译器会使用函数实参的类型来确定模板参数type的类型。

特别注意:

1.编译器会用推断出的模板参数来为我们实例化一个特定版本的函数,换句话说就是编译器会使用实际的模板实参来替代对应的模板参数来创建出一个模板的新“实例”

 template <typename type>
type compare(const type &a,const type &b){
return a>b?a:b;
} int main(){
//实例化为 int compare(const int&,const int&)
cout<<compare(,)<<endl;
//实例化为float compare(const float&,const float&)
cout<<compare(1.2f,2.3f)<<end;
//实例化为double compare(const double&,const double&)
cout<<compare(1.2,2.3)<<endl;
return ;
}

2.当编译器遇到一个模板定义时,它并不生成代码。只有当我们实例化出模板的一个特定版本时,编译器才会生成代码。

3.为了生成一个实例化的版本,编译器需要掌握函数模板的定义,因此与非模板代码不同,模板的头文件通常既包括声明也包括定义

四、函数模板的形参


A、类型形参:类型形参由关见字class或typename后接说明符构成,如:

 template <typename type> //类型形参
void func(type a){
......
}

特别注意:

1.我们可以将类型参数看做类型说明符,就像内置类型或类类型说明符一样使用。

2.不能在函数调用的参数中指定模板形参的类型,对函数模板的调用应使用实参推演来进行,也就是说不能以func(int)的形式调用上面的函数模板func,只能以func(1)的形式调用。


B、非类型形参:非类型形参的参数表示一个值而非一个类型,通常情况下,我们通过一个特定的类型名而非关键字typename或class来指定非类型形参。

特别注意:

1.当一个模板被实例化时,非类型形参会被一个用户提供的或编译器推断出的值所替代,这些值必须是常量

 template <unsigned N,unsigned M>
int compare(const char (&p1)[N],const char (&p2)[M]){ //p1和p2是对数组的引用,而N和M都表示数组的长度
return strcpy(p1,p2);
}

当我们调用这个版本的compare函数时“

compare("Tomwenxing","Jack");

编译器会用字面值常量的大小来代替N和M,从而将模板实例化。另外编译器会在字符串字面常量的末尾插入一个空字符作为终结符,因而编译器最终实例化出的版本如下:

int compare(const char (&p1)[],const char (&p2)[])

2.一个非类型形参可以是一个整型,也可以是一个指向对象或函数类型的指针或引用。其中绑定到非类型整型参数的实参必须是一个常量表达式而绑定到指针或引用非类型参数的实参必须具有静态的生存期

 3.函数模板中需要常量表达式的地方(比如说数组的大小),可以使用非类型形参

C++:模板——函数模板1的更多相关文章

  1. C++学习笔记35:函数模板

    函数模板 函数模板的目的 设计通用的函数,以适应广泛的数据型式 函数模板的定义格式 template<模板型式参数列表>返回值型式 函数名称(参数列表): 原型:template<c ...

  2. C++ template学习一(函数模板和模板函数)

    函数模板和模板函数(1)函数模板函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计.它的最大特点是把函数使用的数据类型作为参数.函数模板的声明形式为:templat ...

  3. 关于C++编译链接和模板函数

    一,关于编译链接编译指的的把编译单元生成目标文件的过程链接是把目标文件链接到一起的过程编译单元:可以认为是一个.c或者.cpp文件.每个编译单元经过预处理会得到一个临时的编译单元.预处理会间接包含其他 ...

  4. 25.C++- 泛型编程之函数模板(详解)

    本章学习: 1)初探函数模板 2)深入理解函数模板 3)多参函数模板 4)重载函数和函数模板 当我们想写个Swap()交换函数时,通常这样写: void Swap(int& a, int&am ...

  5. C++—模板(1)模板与函数模板

    1.引入 如何编写一个通用加法函数?第一个方法是使用函数重载, 针对每个所需相同行为的不同类型重新实现这个函数.C++的这种编程机制给编程者极大的方便,不需要为功能相似.参数不同的函数选用不同的函数名 ...

  6. C++解析(26):函数模板与类模板

    0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...

  7. c++之旅:函数模板

    函数模板 函数模板主要是泛型在函数的中的应用,通过泛型可以让函数处理各种各样的数据类型 简单的列子 #include <iostream> using namespace std; tem ...

  8. C++模板之函数模板实例化和具体化

    模板声明 template<typename/class T>,  typename比class最近后添加到C++标准. 常规模板,具体化模板,非模板函数的优先调用顺序. 非模板函数(普通 ...

  9. C++ 函数模板与类模板(使用 Qt 开发编译环境)

    注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言. 模板是 C++ 支持参数化程序设计的工具,通过它可以实现参数多态性.所谓参数多态性,就是将程序所处理的对象的类型参数化,使得一 ...

随机推荐

  1. 使用XWAF框架(2)——上传文件

    XWAF提供了上传文件的HttpFileUploader工具类,具备强大的多文件上传.文件类型过滤.文件大小限制.存储目录设置.文件名称更改等功能,简化了Web应用开发的编程工作. 它能同时解析表单参 ...

  2. OC 知识:Foundation 框架及相关类详尽总结

    本文用来介绍Foundation框架的相关知识,以及Foundation框架所提供类的相关知识总结. 1. 框架介绍 框架是由很多类.方法.函数和文档按照一定的逻辑组织起来的集合,以使开发程序变得更加 ...

  3. 旧贴-在 win7 / win8 下安装苹果系统 (懒人版)

    前言 该文转载自远景论坛,发布时间2012年,仅供学习参考 这篇安装教程的素材在国庆就准备好了,但那时学习任务比较重,没有时间发帖,一直拖到现在.趁这个周末有空,赶紧写完它,希望能帮助一些景友. 论坛 ...

  4. freemarker时间转换

    Freemarker日期函数处理[转] (2012-08-01 14:32:13)   string(当和一个日期值一起使用) 这个内置标签用指定的格式把日期转换成字符串,(把默认的格式用FreeMa ...

  5. 20155211 课下测试ch12补做

    20155211 课下测试ch12补做 有关线程图,下面说法正确的是() A.图的原点表示没有任何线程完成一条指令的初始状态 B.向右向上是合法的转换 C.向左向下是合法的转换 D.对角线是合法的转换 ...

  6. Qt5.4 All Modules

    Qt5.4 All Modules Qt Essentials Qt essentials define the foundation of Qt on all platforms. They are ...

  7. Kubernetes学习之路(一)之概念和架构解析和证书创建和分发

    1.Kubernetes的重要概念 转自:CloudMan老师公众号<每天5分钟玩转Kubernetes>https://item.jd.com/26225745440.html Clus ...

  8. Object C学习笔记4-内存管理

    Object-C的内存管理和.NET有些不一样,.NET的内存回收机制是使用GC自动处理回收,而Object-C本质上还是C语言,所以很多时候还是需要手动去管理内存回收. 1. Object-C生成一 ...

  9. 十二、基于Django实现RBAC权限管理

    一.RBAC概述 RBAC(Role-Based Access Control,基于角色的访问控制),通过角色绑定权限,然后给用户划分角色. 从企业的角度来说,基本上是按照角色来划分职能.比如,CEO ...

  10. C#/VB.NET与西门子PLC进行ModbusTcp通信

    进入自动化行业半年多了,每天都与机器打交道. 前段时间接手一个任务,需要将我们机台与下站机台进行通讯,我们机台是PC,下站机台为西门子S7-1200. 想想完成这个任务,领导就会对我这个新人刮目相看, ...