模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。

每个容器都有一个单一的定义,比如 向量,我们可以定义许多不同类型的向量,比如 vector  或 vector

您可以使用模板来定义函数和类,接下来让我们一起来看看如何使用。

模板的引入

之前我们知道的交换两个变量的方法有宏定义、函数,这两种方式都能实现两个变量的交换,但是各有各的优缺点

宏定义:#define SWAP(a,b) {a=b-a;b=b-a;a=a+b;}

- 优点:代码复用,适合所有的类型

- 缺点:缺少类型检查,宏在预处理阶段就被替换掉,编译器并不知道宏的存在

函数:

- 优点:真正的函数调用,编译器对类型进行检查

- 缺点:类型不同需要重复定义函数,代码无法复用

上边两种方式都各有利弊,但是在C++中,存在泛型编程的概念:即不考虑具体数据类型的编程方式(如下)

如何定义函数模板

C++中的泛型编程有函数模板与类模板,这章我们先来了解函数模板

函数模板是一种特殊的函数,可以使用不同的类型进行调用,对于功能相同的函数,不需要重复编写代码,并且函数模板与普通函数看起来很类似,区别就是类型可以被参数化

函数模板通过template与typename(或者class)两个关键字来定义,如下

上边就定义了一个变量交换的函数模板,在使用函数模板时有两种方式
    - 自动类型推到调用 Swap(a, b)
    - 具体类型显示调用 Swap(a, b)

下边以代码来体验一下函数模板:

#includeusing namespace std;template <class T>void Swap(T& a, T& b){  T tmp = a;  a = b;  b = tmp;}void main(){  int a = 10;  int b = 20;  Swap(a, b);  //自动推到调用  //Swap(a, b);//显示指定调用  cout <"a = " <"  b = " <endl;  float c = 12.3;  float d = 23.4;  //Swap(c, d); //自动推到调用  Swap<float>(c, d); //显示指定调用  cout << "c = " << c << "  d = " << d << endl;  system("pause");}

可以看到,我们使用函数模板,根据具体类型的参数化,就能适用于不同类型的变量交换,达到了代码复用的效果。

下边来深入理解下函数模板:

- 对于函数模板中使用的类型不同,编译器会产生不同的函数

- 编译器会对函数模板进行两次编译

- 第一次是对函数模板本身进行编译,包括语法检查等

- 第二次是对参数替换后的代码进行编译,这就相当于编译普通函数一样,进行类型规则检查等。

需要注意的是

- 函数模板是不允许隐式类型转换的,调用时类型必须严格匹配

传入不同类型会提示错误。

定义多个类型参数

函数模板还可以定义任意多个不同的类型参数,但是对于多参数函数模板:
    - 编译器是无法自动推导返回值类型的
    - 可以从左向右部分指定类型参数

#include using namespace std;//class typename都可以使用template <class T1, class T2, typename T3>T1 add(T2 a, T3 b){  T1 ret;  ret = static_cast(a + b);  return ret;}void main(){  int c = 12;  float d = 23.4;  //cout << add(c, d) << endl;  //error,无法自动推导函数返回值  cout << add<float>(c, d) << endl;  //返回值在第一个类型参数中指定  cout << add<int, int, float>(c, d) << endl;  system("pause");}

在上边的代码中,我们定义了多类型参数的函数模板,调用时需要注意的是函数返回值需要在第一个参数类型中显示指定,后边的类型可自动推导或显示指定。

函数模板也可以重载

函数模板跟普通函数一样,也可以被重载
    - C++编译器优先考虑普通函数
    - 如果函数模板可以产生一个更好的匹配,那么就选择函数模板
    - 也可以通过空模板实参列表<>限定编译器只匹配函数模板

#include using namespace std;template void fun(T a){  cout << "void fun(T1 a)" << endl;}template void fun(T1 a, T2 b){  cout << "void fun(T1 a, T2 b)" << endl;}void fun(int a, float b){  cout << "void fun(int a, float b)" << endl;}void main(){  int a = 0;  float b = 0.0;  fun(a);  fun(a, b);  //普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数  fun(b, a);  //这个调用,函数模板有更好的匹配,于是调用函数模板  fun<>(a, b);  //限定只使用函数模板  system("pause");}

从输出可以得到,编译器会优先去调用普通函数,但是当函数模板有更好的匹配时或使用限定符<>时,编译器就会去匹配函数模板。

总结

- 函数模板是泛型编程在C++中的应用方式之一

- 函数模板能够根据实参对参数类型进行推导

- 函数模板支持显示的指定参数类型

- 函数模板是C++中重要的代码复用方式

- 函数模板通过具体类型产生不同的函数

- 函数模板可以定义任意多个不同的类型参数

- 函数模板中的返回值类型必须显示指定

- 函数模板可以像普通函数一样重载

公众号ID:C语言Plus扫码关注最新动态

c++ swap函数头文件_C++函数模板(泛型编程)相关推荐

  1. strstr函数头文件_C语言(函数)学习之strstr strcasestr

    一.strstr函数使用 [1] 函数原型 char *strstr(const char *haystack, const char *needle); [2] 头文件 #include [3] 函 ...

  2. strstr函数头文件_strstr函数

    函数名: strstr 功 能: 在串中查找指定字符串的第一次出现 用 法: char *strstr(char *str1, char *str2); 程序例: #include #include ...

  3. c++ cout头文件_C/C++知识分享:C++常用内置函数你会几个,使用过几次呢?

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Regina520 在 C++ 中,除了可以创建各种函数,还包含了各 ...

  4. C语言再学习 -- 常用头文件和函数(转)

    参看:C/C++常用头文件及函数汇总 linux常用头文件如下: POSIX标准定义的头文件 <dirent.h>        目录项 <fcntl.h>         文 ...

  5. listlength函数头文件_酷町问答 - 我们编程时,通常要用到哪些头文件,包含什么函数...

    1.常用数学函数 头文件 #include  或者 #include 函数原型 功能 返回值 int abs(int x) 求整数x的绝对值 绝对值 double acos(double x) 计算a ...

  6. VSCODE编译头文件时函数没有定义的解决方案(VSCODE手动链接C文件方法)

    VSCODE编译头文件时函数没有定义的解决方案(VSCODE手动链接C文件方法) 参考文章: (1)VSCODE编译头文件时函数没有定义的解决方案(VSCODE手动链接C文件方法) (2)https: ...

  7. 【Android FFMPEG 开发】Android Studio 工程配置 FFMPEG ( 动态库打包 | 头文件与函数库拷贝 | CMake 脚本配置 )

    文章目录 I . FFMPEG 交叉编译后的函数库及头文件 II . FFMPEG 静态库打包动态库 ( 仅做参考 ) III . 创建 Android Studio 工程 IV . FFMPEG 头 ...

  8. rt-thread 学习(二)外部中断 添加头文件 延时函数

    rt-thread 学习(二)外部中断 添加头文件 延时函数 设置按键外部中断 开启硬件定时器 初始化配置部分 延时函数 添加头文件 设置按键外部中断 #include <rtthread.h& ...

  9. c语言bzero函数头文件,嵌入q式c语言-文件操用.doc

    嵌入q式c语言-文件操用 广东科学技术职业学院 广州学院 <嵌入式C语言程式设计> 实 验 报 告 专业:计算机应用班级:09计应成绩评定:学号:18姓名:申赟教师签名:谭雄乐实验1题目: ...

最新文章

  1. Python游戏开发,pygame模块,Python实现愤怒的小鸟【附带源码】
  2. HTML5中volume样式自定义,html5中关于volume属性的使用详解
  3. 自顶向下彻底理解 Java 中的 volatile 关键字
  4. mysql中文坑爹的东西
  5. Android网络视频播放器DEMO
  6. 微商分销代理新零售商城源码
  7. 不只是地图应用 带你走进GIS的新世界
  8. Android茶叶进销存源码分享
  9. 基于python的三维射线追踪库-ttcrpy详解(3)
  10. html将英文日期格式转化为中文日期格式,excel中文日期与英文日期的转换
  11. 如何将live stream发布到Youtube
  12. 方舟服务器占用多少内存,方舟生存进化占用多少内存
  13. 【C++ 程序】 TVJ Complex Calculator (v 2.1) 复数计算器
  14. 软件工程作业--网上书店
  15. linux下的go富集分析,GO富集分析示例【华为云技术分享】
  16. Milk Measurement
  17. RSA加密算法加密与解密过程解析
  18. Arduino控制TM1637共阳四位数码管
  19. 服务器系统server2008 qq,WindowsServer2008R2服务器系统安装教程
  20. discuz mysql 类_Discuz论坛中的的MySQL类解析

热门文章

  1. 验证码识别技术(1) - 边缘检测
  2. IT市场10大技术伟人 Linux之父居首(转)
  3. React Native Android启动白屏的一种解决方案下
  4. 异常处理中throws和throw的区别?
  5. 表单界面的兼容PC手机端解决方案
  6. win10更新后程序路径盘符变成*星号解决方法
  7. Jenkins报错‘Gradle build daemon disappeared unexpectedly‘的问题解决
  8. 关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法
  9. 返回,返回无,根本没有返回?
  10. 如何分割字符串以便可以访问项目x?