第20课 - 函数模板

1. C++中如何交换两个变量的值?

void Swap(int& a, int& b)

{

int t = a;

a = b;

b = t;

}

void Swap(float& a, float& b)

{

float t = a;

a = b;

b = t;

}

void Swap(char *& a, char *& b)

{

char *& t = a;

a = b;

b = t;

}

除了类型不同,函数体代码完全相同。C++强调代码复用,那如何来解决代码冗余的问题呢?

2. 泛型编程

不考虑具体类型的编程模式。我们先考虑算法,再考虑类型。

对于Swap函数可以考虑下面的泛型写法

void Swap(T& a, T& b)

{

T t = a;

a = b;

b = t;

}

Swap泛型写法中的T不是一个具体的数据类型,而是泛指任意的数据类型。

(1)函数模板

提供了一种特殊的函数可用不同类型进行调用,看起来和普通的函数很相似,区别是类型可被参数化。

template <typename T>

void Swap(T& a, T& b)

{

T t = a;

a = b;

b = t;}

(2)函数模板的语法规则

template关键字用于声明开始进行泛型编程。

typename关键字用于声明泛指类型。

(3)函数模板的应用

自动类型推导调用

具体类型显示调用

#include <cstdlib>

#include <iostream>

using namespace std;

template<typename T>

void Swap(T& a, T& b)

{

T t = a;

a = b;

b = t;

}

int main(int argc, char *argv[])

{

int a = 1;

int b = 2;

Swap(a, b); //自动类型推导:a和b均是int,因此类型参数T为int

cout<<"a = "<<a<<endl;

cout<<"b = "<<b<<endl;

float fa = 3;

float fb = 4;

Swap<float>(fa, fb);  //显示类型调用:用loat替换参数类型T

cout<<"fa = "<<fa<<endl;

cout<<"fb = "<<fb<<endl;

char ca = 'a';

char cb = 'b';

Swap(ca, cb);

cout<<"ca = "<<ca<<endl;

cout<<"cb = "<<cb<<endl;

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

a = 2

b = 1

fa = 4

fb = 3

ca = b

cb = a

3. 泛型编程初体验(排序算法)

#include <cstdlib>

#include <iostream>

using namespace std;

template<typename T>

void Swap(T& a, T& b)

{

T t = a;

a = b;

b = t;

}

template<typename T>

void SelectSort(T array[], int length)//选择排序

{

for(int i = 0; i<length; i++) //全循环

{

T min = array[i];

int index = i;

for(int j = i+1; j < length; j++)

{

if( array[j] < min)  //找最小

{

min = array[j];

index = j;

}

}

Swap(array[i],array[index]);

}

}

int main(int argc, char *argv[])

{

int array[] = {3, 2, 5, 3 , 4};

SelectSort<int>(array, 5);

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

{

cout<<array[i]<<endl;

}

char ca[] = {'b', 'c', 'a', 'e', 'd', 'f'};

SelectSort(ca, 6);

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

{

cout<<ca[i]<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

2

3

3

4

5

a

b

c

d

e

f

l  函数模板的深入理解:

编译器并不是把函数模板处理成为能够处理任意类型的函数。

编译器从函数模板通过具体类型产生不同的函数。(用几个类型产生几个函数)

编译器会对函数模板进行两次编译:在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。

问:

当函数模板遇到函数重载会发生什么?

4. 函数模板与函数重载

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

#include <cstdlib>

#include <iostream>

using namespace std;

int Max(int a, int b) //与函数模板重名,这两者重载。 这两个函数不会发生冲突。

{

cout<<"int Max(int a, int b)"<<endl;

return a > b ? a : b;

}

template<typename T> //优先考虑普通函数。

T Max(T a, T b)

{

cout<<"T Max(T a, T b)"<<endl;

return a > b ? a : b;

}

template<typename T>

T Max(T a, T b, T c)

{

cout<<"T Max(T a, T b, T c)"<<endl;

return Max(Max(a, b), c);

}

int main(int argc, char *argv[])

{

int a = 1;

int b = 2;

cout<<Max(a, b)<<endl;

cout<<Max<>(a, b)<<endl;

cout<<Max(3.0, 4.0)<<endl;

cout<<Max(5.0, 6.0, 7.0)<<endl;

cout<<Max('a', 100)<<endl; //不允许自动类型转换,只能调用普通函数。

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

int Max(int a, int b)

2

T Max(int a, int b)

2

T Max(int a, int b)

4

T Max(T a, T b, T c)

T Max(int a, int b)

T Max(int a, int b)

7

int Max(int a, int b)

100

注意事项:

函数模板不允许自动类型转化,普通函数能够进行自动类型转换。

cout<<Max(‘a’, 100)<<endl; 必然只会调用普通函数。

5. 多参数函数模板

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

template<typename T1, typename T2, typename RT>

RT Add(T1 a, T2 b)

{

return static_cast<RT>(a + b)

}

cout<<Add<char, float, double >(‘a’, 100)<<endl;

问题:

多类型参数的模板可以进行自动类型推导吗?

当生命的类型参数为返回值类型时,无法进行自动类型推导。

#include <cstdlib>

#include <iostream>

using namespace std;

template<typename RT, typename T1, typename T2>

RT Add(T1 a, T2 b)

{

return static_cast<RT>(a + b);

}

int main(int argc, char *argv[])

{

cout<<Add<double, char, float>('a', 100.0f)<<endl;

cout<<Add<double>('a', 100.0f)<<endl;   //只定义返回值类型

//cout<<Add('a', 100.0f)<<endl;  这样写会报错

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}运行结果:

197

197

l  不完美的解决方案

将返回值类型参数声明到第一个参数的位置,调用时只需显示声明反水类型参数即可。

小结:

函数模板起始是一个具有相同行为的函数家族。

函数模板可以根据类型实参对函数进行推导调用。

函数模板可以显示指定的类型参数。

函数模板可以被重载。

转载于:https://www.cnblogs.com/free-1122/p/11336241.html

C++--第20课 - 函数模板相关推荐

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

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

  2. C++编程——函数模板

    文章目录 1 函数模板语法 2 函数模板注意事项 3 函模模板案例 4 普通函数与函数模板的区别 5 普通函数与函数模板的调用规则 6 模板的局限性 模板就是建立通用的模具,大大提高复用性 模板的特点 ...

  3. 模板有函数模板和类模板,这个在上学期的java课里面就学了,C++应该是一样的。

    模板有函数模板和类模板,这个在上学期的java课里面就学了,C++应该是一样的. .

  4. 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)

    0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...

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

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

  6. C++知识点55——函数模板

    一.为啥需要模板 防止相同功能的重复实现 二.函数模板 1.模板函数的定义 template <typename T> const T& Max(const T &a, c ...

  7. c++ swap函数头文件_C++函数模板(泛型编程)

    模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码. 模板是创建泛型类或函数的蓝图或公式.库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念. 每个容器都有一个单 ...

  8. 普通函数与函数模板的区别

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

  9. C++函数模板Demo - win32 版

    C++ 模板 模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码. 模板是创建泛型类或函数的蓝图或公式.库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念. 每个 ...

  10. C++ 函数模板特化导致的多重定义链接错误

    转载请注明文章:C++ 函数模板特化导致的多重定义链接错误 出处:多客博图 标题说的可能不是很清楚,解释一下,函数模板,一般都是放在头文件里面,所以有些时候,我也会做一个特化,也放在这个头文件里面,当 ...

最新文章

  1. mysql搜索规则_MySQL基于规则优化
  2. 用正则实现多行文本合并,从而保存为csv文件
  3. JavaFX官方教程(五)之在JavaFX中创建表单
  4. jenkins发送allure测试报告附件
  5. Ionic如何实现单选二级菜单切换
  6. SolarWinds与安稳特加强合作关系,携手助力中国IT专业人士应对挑战
  7. Redis BigKey
  8. ACM_一道耗时间的水题
  9. linux下实现在程序运行时的函数替换(热补丁)
  10. 什么?吴宗宪在淘宝帮你买买买?
  11. CSDN账号绑定github(极简办法)
  12. 计算机常见错误代码,电脑常见错误蓝屏代码汇总及解决方法
  13. 【01】SylixOS下LWIP的实现---动态内存管理
  14. ios原生条形码扫描 效率低下原因
  15. Java+PDFBox将PDF转成图片
  16. redis集群-局域网中两台电脑通信
  17. 成功真正需要什么:情商德商及体商 别高估智商
  18. Android开发支付集成——微信集成
  19. Android 蓝牙开发——蓝牙连接(六)
  20. 国内最优质的10个小众网站,你知道几个?

热门文章

  1. linux下的用户的管理(创建用户,删除用户)
  2. 一个酷炫的音乐播放界面
  3. 最牛逼android上的图表库MpChart(三) 条形图
  4. python terminal_一个简单、易用的Python命令行(terminal)进度条库
  5. c++ 一个函数包括多个返回值判断_整活函数式编程
  6. mysql 1236错误_MySQL主主同步环境出现1236错误
  7. android自动修音,唱吧自动修音app下载-唱吧自动修音 安卓版v8.6.0-PC6安卓网
  8. 安装linux没有raid驱动程序,LINUX 无法在 RAID 上安装的问题
  9. python键值对储存数据_在python中存储100万个键值对的列表
  10. 一、在Linux下,Nginx初安装及简单配置