当前课程知识点:C++语言程序设计进阶 >  第九章 模板与群体数据 >  模板 >  函数模板

返回《C++语言程序设计进阶》慕课在线视频课程列表

函数模板在线视频

函数模板

函数模板

例:求绝对值函数的模板

9-1.png

9-2.png

函数模板定义语法

函数定义

例9-1 函数模板的示例

//9_1.cpp
#include <iostream>
using namespace std;

template <class T>  //定义函数模板
void outputArray(const T *array, int count) {
    for (int i = 0; i < count; i++)
        cout << array[i] << " "; //如果数组元素是类的对象,需要该对象所属类重载了流插入运算符“<<”
    cout << endl;
}

int main() {     
    const int A_COUNT = 8, B_COUNT = 8, C_COUNT = 20;
    int a [A_COUNT] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    double b[B_COUNT] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 };
    char c[C_COUNT] = "Welcome!";

    cout << " a array contains:" << endl;
    outputArray(a, A_COUNT);    
    cout << " b array contains:" << endl;
    outputArray(b, B_COUNT);    
    cout << " c array contains:" << endl;
    outputArray(c, C_COUNT);    
    return 0;
}
运行结果如下:
a array contains:
1 2 3 4 5 6 7 8
b array contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 
c array contains:
W e l c o m e!

注意



下一节:类模板

返回《C++语言程序设计进阶》慕课在线视频列表

函数模板课程教案、知识点、字幕

大家好

欢迎继续学习C++语言程序设计

这一节我们来学习函数模板

大家有没有这样的经历呢

可能我们写一个函数

它的主体逻辑都是一样的

但是

当我们需要用这样的算法逻辑

去处理不同类型数据的时候呢

我们就要为它写不同的重载函数

比如说

如果我们要写一个

求绝对值的函数

不管你去求整数的绝对值

还是浮点数的绝对值

那么它的算法逻辑都是一样的

但是呢

由于处理的数据类型不同

也就是函数的参数不同

我们就要写多种重载形式的

重载函数

实际上是C++里面

很好的一种机制

但是重载函数

它是对函数的使用者

提供了很大的方便

那么函数的编写者

你还是要写多个重载的函数体

那么多个完全一样

或者是几乎一样的重载函数体

带来的问题不仅仅是冗余

还有可能呢

当你在修改算法的时候

如果没有在各个函数体中

进行同步的修改的话呢

还会造成

你在同一个系统中

处理同类型的问题

用的算法不一致

那么这就是不一致性的问题

其实呢

C++解决这种问题

有一个非常好的办法

就是用函数的模板

接下来呢

我们先通过一个简单的例子

也就是求绝对值函数的例子

来感觉一下

为什么我们需要函数模板

函数模板能为我们节省

什么样的工作量

带来什么样的便利

现在我们看到这里

是两个求绝对值的函数

这两个函数的函数体

语句都是一样的

只是它们的参数类型不一样

那么像这样的重载形式的函数

我们如果这样写

多个重载的函数体呢

实际上是冗余的

在C++中呢

我们可以有比较好的方案

解决这样的冗余问题

就是使用函数模板

我们可以创建一个通用的函数

实际上就是一个函数模板

它可以支持多种不同的形参类型

这样就可以简化

重载函数的函数体设计

具体的呢我们来看看

将这两种函数合在一起

两个重载形式合在一起

实际上它的函数体是一样的

那么它参数类型怎么写呢

写成抽象类型

可定制的类型

这个T类型呢

实际上就是类型参数

我们看到在这个函数头上

这儿有template关键字

后面这有尖括号

尖括号里面呢

就列出来是类型参数

这个类型参数呢

在我们运行的时候

需要调用函数的时候

可以去指定这个类型参数

我们来看这个例子中

定义好了这样的函数模板以后

在主函数中呢

看我们首先调用

求绝对值的函数abs

第一次给的这个参数

是一个int类型的参数n

int类型的

那么编译器在编译的时候

可以根据这个实参的类型

它推导出

在这次调用的时候呢

模板里面的这个T应该为int

因此呢

编译器就会以这个模板为依据

将T都替换为int

为我们生成了一个

可以使用的这个真正的函数

函数模板就不可以直接被调用的

那么调用的时候

都要生成一个函数

这是由编译器生成的

所以这就生成了一种

重载形式的函数

它接收int参数 返回int值

那么在第二次调用的时候呢

给它的这个参数d

是个double类型

同样的道理

编译器因此就推导出

这一次调用的时候

应该将T 替换为double

然后编译器

又为我们生成了一个函数

那第二次调用的呢

是这个接收double类型参数的

这种重载形式的函数

那么我们看到

运行结果分别得到了

整数的绝对值

和浮点数的绝对值

好 看了上面的例子以后呢

接下来我们来看看

函数模板的语法是什么样的

那么定义函数模板呢

要用template关键字

后面尖括号里面是模板参数表

这个是定义普通函数的时候

没有的

那么这个模板参数表里面

容纳的是什么东西呢

实际上就是类型参数

在此之前我们只用过数据参数

函数的形参表里面

列出来都是数据参数

其实类型也是可以作为参数的

类型参数要用到class

或者typename关键字

然后要有标识符

这个标识符呢

就代表一个抽象的类型

那在模板的参数表中

也可以有常量参数

下面呢

我们再来看一个函数模板的例子

这个例题中呢

定义了一个函数模板outputArray

用来输出数组的元素

那么这个数组

它是什么类型的数组呢

数组元素类型用的是

一个抽象的类型

也就是类型参数 T类型

这样的话

这个函数模板就比较通用

可以用来输出

任何类型的一维数组的元素

但是呢

我们也要注意

将来我们使用的时候

打算用它来输出

什么类型的数组呢

如果是基本类型的数组

没有问题

都可以执行这个插入运算

去输出数组的元素

如果这个数组的元素类型

是对象

那么我们就要看一下

这个对象所属的类

是否重载了比如插入运算符

如果它没有重载流插入运算符

我们硬是要用它输出数组元素

那程序会出错的

所以这个时候就要做一下检查

如果没有重载的话呢

需要重载

我们为类重载一下

这个插入运算符

好 现在我们来看在主函数中

用一下这个函数模板

为此我们提前准备好了

三个不同类型的数组

int数组 double数组

和字符数组

然后呢

分别三次调用这个函数模板

实际上在这三次调用的时候呢

编译器都会根据

我们的数组元素的类型呢

去置换这个T

为我们生成每一次

针对这个类型

适用的outputArray函数

这样

编译器实际上为我们生成了

三种重载形式的outputAarray

分别接收不同类型的数组

那我们看到运行结果

正确地输出了每一种

不同类型的数组中的元素

看了这样两个

函数模板的例题以后

大家一定会觉得

模板真是个好东西

但是它也不是

放之四海而皆准的 万能的

本来

不同的运算符

会适用于不同的数据类型

尤其是我们自定义类型

如果我们没有为这个类型

重载某些运算符

那这些运算符

就不能用在这个类型上

所以使用模板的时候

并不是说我们写一个模板

然后给它指定任意类型

编译器都可以为我们

生成合适的函数

我们给模板去指定

类型参数的时候

这个类型

必须能够进行模板函数

函数体所写出来的那些运算

比如说

插入运算符

比如说加法运算符

它能用吗

能用我们才可以给这个类型实参

如果不能用呢

比如说是自定义类型

我们也想用这个函数模板

来处理它

怎么办呢

先给自定义类型

去重载相关的运算符

C++语言程序设计进阶课程列表:

第七章 继承与派生

-导学

--导学

-继承的基本概念和语法

--继承的基本概念和语法

-第七章 继承与派生--继承的基本概念和语法习题

-继承方式

--继承方式简介及公有继承

--私有继承和保护继承

-第七章 继承与派生--继承方式

-基类与派生类类型转换

--基类与派生类类型转换

-第七章 继承与派生--基类与派生类类型转换

-派生类的构造和析构

--派生类的构造函数

--派生类的构造函数举例

--派生类的复制构造函数

--派生类的析构函数

--第七章 继承与派生--派生类的构造和析构

-派生类成员的标识与访问

--访问从基类继承的成员

--虚基类

-第七章 继承与派生--派生类成员的标识与访问

-小结

--小结

-综合实例

--第七章综合实例

-实验七

--实验七

-第七章讲义

第八章 多态性

-导学

--导学

-第八章 多态性--导学

-运算符重载

--运算符重载的规则

--双目运算符重载为成员函数

--单目运算符重载为成员函数

--运算符重载为非成员函数

-第八章 多态性--运算符重载

-虚函数

--虚函数

--虚析构函数

--虚表与动态绑定

-第八章 多态性--虚函数

-抽象类

--抽象类

--第八章 多态性--抽象类

-override与final

--override与final

-第八章 多态性--override与final

-小结

--第八章小结

-综合实例

--第八章综合实例

-实验八

--实验八

- 第八章讲义

第九章 模板与群体数据

-导学

--导学

-模板

--函数模板

--类模板

-第九章 模板与群体数据--模板

-线性群体

--线性群体的概念

-第九章 模板与群体数据--线性群体

-数组

--数组类模板

--例9-4数组类应用举例

-链表

--链表的概念与结点类模板

--链表类模板

-第九章 模板与群体数据--链表

-栈

--栈类模板

--栈类模板课后习题

--例9-9 栈的应用

--例9-9 栈的应用课后习题

-队列

--队列类模板

-第九章 模板与群体数据--队列

-排序

--排序概述

--插入排序

--选择排序

--交换排序

-第九章 模板与群体数据--排序

-查找

--查找

--查找课后习题

-小结

--小结

-综合实例

--综合实例

-实验九

--实验九

- 第九章讲义

第十章 泛型程序设计与C++标准模板库

-导学

--导学

-泛型程序设计及STL的结构

--泛型程序设计的基本概念

--STL简介

-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构

-迭代器

--迭代器

-第十章 泛型程序设计与C++标准模板库--迭代器

-容器的基本功能与分类

--容器的基本功能与分类

-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类

-顺序容器

--顺序容器的基本功能

--顺序容器的特征

--顺序容器的插入迭代器与适配器

--第十章 泛型程序设计与C++标准模板库--顺序容器

-关联容器

--关联容器分类和基本功能

--集合

--映射

--多重集合和多重映射

-第十章 泛型程序设计与C++标准模板库--关联容器

-函数对象

--函数对象

--函数适配器

-算法

--算法

-小结

--第十章小结

-综合实例

--综合实例

-实验十

--实验十

- 第十章讲义

第十一章 流类库与输入/输出

-导学

--导学

-I/O流的概念及流类库结构

--I/O流的概念及流类库结构

-第十一章 流类库与输入/输出--I/O流的概念及流类库结构

-输出流

--输出流概述

--向文本文件输出

--向二进制文件输出

--向字符串输出

-第十一章 流类库与输入/输出--输出流

-输入流

--输入流概述

--输入流应用举例

--从字符串输入

-第十一章 流类库与输入/输出--输入流

-输入/输出流

--输入/输出流

-第十一章 流类库与输入/输出--输入/输出流

-小结

--小结

-综合实例

--综合实例

-实验十一

--实验十一

- 第十一章讲义

第十二章 异常处理

-导学

--第12章导学

-异常处理的思想与程序实现

--异常处理的思想与程序实现

-第十二章 异常处理--异常处理的思想与程序实现

-异常处理中的构造与析构

--异常处理中的构造与析构

-第十二章 异常处理--异常处理中的构造与析构

-标准程序库异常处理

--标准程序库异常处理

-第十二章 异常处理--标准程序库异常处理

-小结

--第12章小结

-综合实例

--综合实例

-实验十二

--实验十二

- 第十二章讲义

函数模板笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。