文章目录

  • 1 函数模板语法
  • 2 函数模板注意事项
  • 3 函模模板案例
  • 4 普通函数与函数模板的区别
  • 5 普通函数与函数模板的调用规则
  • 6 模板的局限性

模板就是建立通用的模具,大大提高复用性
模板的特点:

  • 模板不介意直接使用,它只是一个框架
  • 模板的通用并不是万能的

C++另一种编程思想称为泛型编程,主要利用的技术就是模板
C++提供两种模板机制:函数模板类模板
本文介绍的是函数模型的知识

1 函数模板语法

函数模板作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表
语法

template<typename T>
函数声明或者定义

解释:
template声明创建模板
typename表示其后面的符号是一种数据类型,可以用class代替
T是通用的数据类型,名称可以替换,通常为大写字母

示例
假设有这么一个场景,想要实现两个数的交换,代码如下:

//两个整型交换的函数
void swapInt(int &a, int &b)
{int temp = a;a = b;b = temp;
}//两个浮点型交换的函数
void swapDouble(double &a, double &b)
{double temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;swapInt(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;double c = 30;double d = 40;swapDouble(c, d);cout << "c = " << c << endl;cout << "d = " << d << endl;}int main()
{test01();system("pause");return 0;
}

如果按照上面的这种写法,每一个数据类型,都要写一个交换的函数。但是仔细看不同数据类型中交换函数的代码,其实差异性不是很大。此时,如果利用模板的技术,将大大提高代码的复用性,基于模板技术的代码如下:

//函数模板
template<typename T> //声明一个模板,告诉编译器后面代码中紧跟的T不要报错,T是一个通用数据类型
void mySwap(T &a, T &b)
{T temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;//利用函数模板交换//两种方式使用函数模板// 1、自动类型推导mySwap(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;double c = 30;double d = 40;// 2、显式指定类型mySwap<double>(c, d);cout << "c = " << c << endl;cout << "d = " << d << endl;}int main()
{test01();system("pause");return 0;
}

总结:

  • 函数模板利用关键字template
  • 使用函数模板有两种方式:自动类型推导、显示指定类型
  • 模板的目的是为了提高复用性,将参数类型化

2 函数模板注意事项

注意事项:

  • 自动类型推导,必须推导出一致的数据类型T才可以使用
  • 模板必须要确定出T的数据类型才可以使用

3 函模模板案例

案例描述:

  • 利用函数模板封装一个排序函数,可以对不同数据类型数组进行排序
  • 排序规则从大到小,排序算法为选择排序

示例

#include <iostream>
using namespace std;
#include <string>//交换函数模板
template<class T>
void mySwap(T &a, T &b)
{T temp = a;a = b;b = temp;
}//排序算法
template<typename T> //声明一个模板,告诉编译器后面代码中紧跟的T不要报错,T是一个通用数据类型
void mySort(T arr[], int len)
{for (int i = 0; i < len; i++){int max = i; //认定最大值的下标for (int j = i; j < len; j++){//认定的最大值比遍历出的数值要小,说明j下标的元素才是真正的最大值if (arr[max] < arr[j]){max = j; //更新最大值下标}}//交换max和i元素mySwap(arr[max], arr[i]);}
}//提供打印数组模板
template<typename T>
void printArray(T arr[], int len)
{for (int i = 0; i < len; i++){cout << arr[i] << " ";}cout << endl;
}void test01()
{//测试char数组char charArr[] = "badcfe";int num = sizeof(charArr) / sizeof(char);mySort(charArr, num);printArray(charArr, num);
}int main()
{test01();system("pause");return 0;
}

4 普通函数与函数模板的区别

普通函数与函数模板的区别:

  • 普通函数调用时可以发生自动类型转换(隐式类型转换)
  • 函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
  • 函数模板中如果利用显示指定类型的方式,可以发生隐式类型转换

示例

//普通函数
int myAdd01(int a, int b)
{return a + b;
}//函数模板
template<class T>
int myAdd02(T a, T b)
{return a + b;
}void test01()
{int a = 10;int b = 20;char c = 'c';cout << myAdd01(a, c) << endl;//自动类型推导cout << myAdd02(a, b) << endl;//cout << myAdd02(a, c) << endl;会报错,T的类型不一致//显示指定类型myAdd02<int>(a, c); //不会报错,会发生隐式类型转换}int main()
{test01();system("pause");return 0;
}

5 普通函数与函数模板的调用规则

调用规则如下:

  • 如果函数模板和普通函数都可以实现,优先调用普通函数
void myPrint(int a, int b)
{cout << "调用的普通函数" << endl;
}template<typename T>
void myPrint(T a, T b)
{cout << "调用的是函数模板" << endl;
}void test01()
{int a = 10;int b = 20;myPrint(a, b);}int main()
{test01();system("pause");return 0;
}

运行结果:

  • 可以通过空模板参数列表来强制调用函数模板
void myPrint(int a, int b)
{cout << "调用的普通函数" << endl;
}template<typename T>
void myPrint(T a, T b)
{cout << "调用的是函数模板" << endl;
}void test01()
{int a = 10;int b = 20;myPrint<>(a, b);}int main()
{test01();system("pause");return 0;
}

运行结果:

  • 函数模板也可以发生重载
template<typename T>
void myPrint(T a, T b)
{cout << "调用的是函数模板" << endl;
}template<typename T>
void myPrint(T a, T b,T c)
{cout << "调用的是重载的函数模板" << endl;
}void test01()
{int a = 10;int b = 20;myPrint(a, b, 100);}int main()
{test01();system("pause");return 0;
}

运行结果:

  • 如果函数模板可以产生更好的匹配,优先调用函数模板
void myPrint(int a, int b)
{cout << "调用的普通函数" << endl;
}template<typename T>
void myPrint(T a, T b)
{cout << "调用的是函数模板" << endl;
}void test01()
{char c1 = 'a';char c2 = 'b';myPrint(c1, c2);}int main()
{test01();system("pause");return 0;
}

运行结果:

6 模板的局限性

局限性:模板的通用并不是万能的
示例1

template<class T>
void f(T a, T b)
{a = b;
}

在上述代码中提供的赋值操作,如果传入的ab是一个数组,就无法实现了

示例2

template<class T>
void f(T a, T b)
{if (a > b){}
}

在上述代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行

因此C++为了解决这种问题,提供了模板的重载,可以为这些特定的类型提供具体化的模板

示例

class Person
{public:Person(string name, int age){this->m_Age = age;this->m_Name = name;}int m_Age;string m_Name;
};//对比两个数据是否相等
template<typename T>
bool myCompare(T &a, T &b)
{if (a == b){return true;}else{return false;}
}
//利用具体化Person的版本实现代码,具体化优点调用
template<> bool myCompare(Person &p1, Person &p2)
{if (p1.m_Age == p2.m_Age && p1.m_Name == p2.m_Name){return true;}else{return false;}
}void test01()
{Person a("Tom", 10);Person b("Tom", 10);bool ret = myCompare(a, b);if (ret){cout << "a == b" << endl;}else{cout << "a != b" << endl;}}int main()
{test01();system("pause");return 0;
}

如果不写具体化的版本,代码就会报错。原因是出现自定义类型的比较时,编译器无法识别。可以在Person类中重载==运算符的形式来解决问题,但是有些麻烦。所以上述代码采用模板具体化的方式来解决。

总结:

  • 利用具体化的模板,可以解决自定义类型的通用化
  • 学习模板并不是为了写模板,而是在STL能够运用系统提供的模板

注:本文参考b站黑马程序员C++课程

C++编程——函数模板相关推荐

  1. 【C++ 语言】面向对象 ( 模板编程 | 函数模板 | 类模板 )

    文章目录 函数模板 类模板 代码示例 函数模板 1. 模板编程 : 类似于 Java 中的泛型编程 ; ① 函数模板 : 对应着 Java 中的泛型方法 ; ② 类模板 : 对应 Java 中的泛型类 ...

  2. c++ 函数模板_C/C++编程笔记:C++入门知识,深入解析C++函数和函数模板

    本篇要学习的内容和知识结构概览 函数的参数及其传递方式 1. 函数参数传递方式 传值: 传变量值: 将实参内存中的内容拷贝一份给形参, 两者是不同的两块内存 传地址值: 将实参所对应的内存空间的地址值 ...

  3. C++笔记7:C++提高编程1:模板—[函数模板和类模板]

    0820 C++提高编程: 1.模板-[函数模板和类模板] 2.初识STL 3.STL-常用容器 4.STL-函数对象 5.STL-常用算法 C++提高编程引言: C++除了面向对象编程思想,还有泛型 ...

  4. C++编程进阶7(何时使用成员函数模板,模板类的实参推断与类型转换、继承与数组)

    二十六.何时使用成员函数模板 关于成员函数模板见https://blog.csdn.net/Master_Cui/article/details/111824152 成员函数模板主要用来兼容不同类型的 ...

  5. c++面向对象高级编程 学习十一 类模板、函数模板、成员模板

    namespace经验谈: 团队中函数或类的名字可能会冲突,因此使用namespace进行区分. 类模板: template<typename T> 函数模板: template<c ...

  6. c++面向对象高级编程 学习四 静态、类模板、函数模板

    静态static:静态数据和静态函数,在内存中只有一份,不会随着创建对象的数目的增加而增加 static数据:比如银行的account类中,账户名是普通数据,100个对象会有100个账户名,但利率都是 ...

  7. C语言小知识:typedef\函数模板\

    (1)typedef用法: typedef为C语言的关键字,作用是为一种数据类型定义一个新名字.这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等).在编程中使用t ...

  8. C++_static,类模板、函数模板、namespace

    C++_static,类模板.函数模板.namespace 1.static 2.类模板 3.函数模板 4.namespace 5.深入,更多细节 参考:侯捷<C++面向对象高级编程>

  9. 判断exception类型_C++核心准则T.44:使用函数模板推断类模板参数类型(如果可能)...

    T.44: Use function templates to deduce class template argument types (where feasible) T.44:使用函数模板推断类 ...

最新文章

  1. JavaScript检查null与undefined以及==和===之间的差异
  2. 2021年JVM生态中哪些是流行的、热门的、趋势是什么
  3. python turtle画气球-使用python在mac上简单弹出气球消息
  4. Delphi应用程序的调试(二)使用断点
  5. BOMHEAD display issue
  6. 【Java中级篇】使用zxing生成二维码
  7. Fabric node sdk 1.4简明教程
  8. iptables防火墙工作原理及简单配置访问策略
  9. Halcon基于形状的几何定位函数说明
  10. 翻译: 4.2. 从零开始实现多层感知器MLP pytorch
  11. 地图可视化开发技巧:geojson转svg后再转emf格式插入ppt实现编辑的解决方案
  12. python使用匿名函数计算长方形的面积
  13. 你和语言模型,谁的填空能力更强?
  14. 关于使用win10易升,升级后电脑变卡解决方法
  15. 【django接口自动化1】环境搭建
  16. c++编程题 袋鼠过河
  17. 超融合一体机分布式存储
  18. JAVA POI WORD XWPFDocument 常用操作-随时更新
  19. word选中段尾不选回车符
  20. 通过读取/proc/cpuinfo获取CPU信息

热门文章

  1. iphone投屏到mac
  2. pip 与 pip3 区别
  3. 新股上市当天有涨跌幅限制吗?
  4. vue引入阿里iconfont
  5. BusyBox下载安装教程
  6. goland里的异常处理
  7. LED数字量:LED闪烁、跑马灯效果
  8. 一个更加牛逼的科技媒体将如何崛起
  9. mac php开发套件_mac php集成开发环境搭建软件推荐(附教程)
  10. vue 调用微信分享接口 分享截图图片