转载请保留以下声明
  作者:赵宗晟
  出处:http://www.cnblogs.com/zhao-zongsheng/p/8493398.html

前言

有些人提到C++模板就会下意识地觉得可怕、看不懂、避而远之。其实模板并不复杂,而且熟练后可以用在日常工作中,可以帮助我们重用代码,让代码更简洁、易读、可维护。希望这个系列的文章,能够让更多人发现模板的魅力,帮助大家写出更高质量的代码。

我们为什么需要模板

我们有时候会遇到这样的情况:同样的函数,我们要为不同的类型写不同的版本,内容与逻辑都是一摸一样的,只有他们的类型不一样。比如我们写一个max函数,传入两个数字,返回大的数字。很自然地,两个参数的类型和返回的类型必须是相同的。如果不使用模板,我们需要使用函数重载,为不同的类型写不同的函数:

int max(int a, int b)
{
return a < b ? b : a;
} float max(float a, float b)
{
return a < b ? b : a;
}

这里我只写了2个函数,实际上short, long, unsigned, double等等类型都需要专门的max函数,结果就是需要写十几个几乎一摸一样的代码。如果函数功能更复杂一些,函数实现需要更多行,就会出现大量冗余重复的代码,而且不容易维护,很容易出错。这个时候如果我们能够根据特定的模板批量生成一系列代码,将会方便很多。为此,我们可以使用C++中的模板

什么是模板

顾名思义,模板就是编译器生成代码用的模子。模板有两类,函数模板和类模板(C++14开始出现了变量模板,不过不在此讨论)。如果想要生成函数代码,则需要用函数模板,如果想要生成类定义,则需要用到类模板。这篇文章会先介绍函数模板,下篇文章再介绍类模板。

函数模板

我们可以为上面的一系列max函数写一个函数模板。

template<typename T>
T max(T a, T b)
{
return a < b ? b : a;
}

我们暂时不细说语法,先看一看大致的样子,其实函数模板的长相和普通的函数是很像的。

好了,我们已经定义了一个函数模板,那么怎么去生成函数代码?事实上我们不需要做额外的事情,如果我们使用了max函数,编译器就会自动帮我们生成对应类型的代码。函数模板的使用方式很简单,只需要在模板的名字后面写一对尖括号,尖括号内写上实参列表就可以使用了。

double d = max<double>(1.2, 2.4);

编译器看到这一行,就会自动帮我们生成double版本的max函数,生成出来的函数等价于把函数模板中的所有T都替换成double。在这里max<double>可以看做是double版本的max函数的函数名,我们甚至还可以用&max<double>来获取这个函数的地址。

我们来看一个更复杂的例子

template<typename T, int i>
T create()
{
T value();
return value + i;
} int main()
{
float f1 = create<float, >(); // f1 == 1.0
float f2 = create<float, >(); // f2 == 2.0
}

这个例子里面我们定义了一个create函数模板,根据模板创建并使用了两个函数create<float, 1>和create<float, 2>。要注意的是,这两个函数是不同的函数,有不同的函数体,和不同的函数地址。他们两个分别等价于

float create()    // create<float, 1>
{
float value();
return value + ;
} float create() // create<float, 2>
{
float value();
return value + ;
}

我们总结一下函数模板的语法,模板定义由template关键字开始,后面跟着一对尖括号,尖括号里面是模板形参列表,也就是模板的参数。模板形参列表的写法和函数形参列表的写法是很相似的。都是“类型 参数名, 类型 参数名, ...”这种形式。上面的例子中,模板形参列表就是“typename T, int i”。我们注意到,模板形参列表需要为每个形参指定一个类型,这个是因为形参不一定是C++类型,还可以是具体的值,例如数字,指针等等。如果形参是一个类型,则需要使用typename关键字来表示形参的类型,如果形参是一个值,则需要写上这个值的类型。在使用模板的时候,要在模板的名字后面加一对尖括号,尖括号里面是模板实参列表,在上面的例子中,实参列表就是“float, 1”和“float, 2”。与函数调用类似,使用模板的时候编译器会检查实参列表的类型与形参列表的类型是否匹配,不匹配的话会报错。

使用函数模板的优点

我们可以从上面的例子中看出,用函数模板更方便简洁,不需要重复写类似的重载函数。除此外,因为函数代码是在使用的时候生成出来的,所以如果我们没有使用这个函数,编译器就不会生成这个代码,这样我们可以减小程序的大小。例如,我们使用了max<double>,但是没有使用max<int>,那么程序中只有max<double>函数,不会有max<int>函数。

C++模板入门教程(一)——模板概念与基本语法的更多相关文章

  1. FineReport----报表模板入门教程1

    FineReport就一款类Excel操作界面的报表工具,通过拖拖拽拽简单实现报表制作,实现数据展示.数据查询.数据录入功能,并且支持图形多样化展示. 一.入门小例子 1. 打开设计器 启动FineR ...

  2. git 入门教程之基本概念

    基本概念 了解工作区,暂存区和版本库的区别和联系有助于我们更好理解 git 的工作流程,了解命令的操作意图. git 和其他版本控制系统如 svn 的不同之处就是有暂存区的概念. 基本概念 工作区 | ...

  3. 一步步Cobol 400 上手自学入门教程01 - 基础概念

    先学习基础概念 1.COBOL字符:包含: User-defined words 用户定义字符 ŸSystem-names ŸReserved words 关键字 2.用户定义字符User-defin ...

  4. MobX快速入门教程(重要概念讲解)

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7372119.html 一:Mobx工作流程图 二:MobX涉及到的概念 1:状态state 组件中的数据. 2 ...

  5. 程序员,一起玩转GitHub版本控制,超简单入门教程 干货2

    本GitHub教程旨在能够帮助大家快速入门学习使用GitHub,进行版本控制.帮助大家摆脱命令行工具,简单快速的使用GitHub. 做全栈攻城狮-写代码也要读书,爱全栈,更爱生活. 更多原创教程请关注 ...

  6. Linux Cgroup 入门教程:cpuset

    这是 Cgroup 系列的第四篇,往期回顾: Linux Cgroup 入门教程:基本概念 Linux Cgroup 入门教程:CPU Linux Cgroup 入门教程:内存 通过上篇文章的学习,我 ...

  7. pageadmin CMS网站制作教程:模板概念解释

    pageadmin CMS网站建设教程:模板概念解释 1.模板页 又叫视图页面,PageAdmin后台栏目或信息中用到的模板页面的统称,格式必须是.cshtml后缀文件,前端人员制作的页面默认都是ht ...

  8. mui初级入门教程(六)— 模板页面实现原理及多端适配指南

    文章来源:小青年原创发布时间:2016-07-26关键词:mui,webview,template,os,多端适配转载需标注本文原始地址: http://zhaomenghuan.github.io. ...

  9. CPF 入门教程 - 设计器和模板库的使用(五)

    CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF ...

随机推荐

  1. 利用ffmpeg做视频解码的顺序

    这几天在实验室捣鼓着用ffmpeg做视频解码,终于把数据解出来了,虽然还没有做显示部分,不知道解码解得对不对,但料想是不会有什么问题了.回头看看这几天的工作,其间也遇到了不少问题,主要还是对ffmpe ...

  2. ASI通讯协议——ASI2x1

    通讯协议--ASI2x1 基本功能描述 计算机或控制器通过以太网口或者RS232接口发出指令,包括查询指令,切换指令等,主机箱中的控制板在收到这些指令之后,将这些数据通过485总线转发给对应的主板,并 ...

  3. 蜻蜓FM 涉嫌诈骗投资人和广告主源代码剖析

    本文主要内容,引用自知乎的这篇文章:如何评价蜻蜓 FM 伪造用户活跃度等数据 感谢"左莫"."任正"等热心正义的网友--左莫,任正的最早的回答猜测已经被蜻蜓FM ...

  4. dedecms 在php5.4以上环境下 无法保存中文

    dedecms gbk版本在php5.4以上环境下 无法保存中文 原因在于5.4.0对这个函数的变化:htmlspecialchars5.4.0   The default value for the ...

  5. 错误号码2003 Can't connect to MySQL server 'localhost' (0)

    错误描述 错误原因 最近,我一直都可以用SQLyog连接本地数据库,但是近几天却无法连接:并且一直都报上述错误,我查阅了很多资料,发现有很多中说法 总结一下 第一,MySQL中的my.ini出错: 第 ...

  6. hi3531 SDK 编译 uboot, 修改PHY地址, 修改 uboot 参数 .

    一,编译uboot SDK文档写得比较清楚了,写一下需要注意的地方吧. 1. 之前用SDK里和别人给的已经编译好的uboot,使用fastboot工具都刷不到板子上.最后自己用SDK里uboot源码编 ...

  7. Exception sending context initialized event to listener instance of class

    1.错误描述 严重:Exception sending context initialized event to listener instance of class org.springframew ...

  8. Supermarket POJ - 1456

    A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold ...

  9. var dataObj=eval("("+data+")");//转换为json对象(解决在ajax返回json格式数据的时候明明正确的获取了返回值但是却就是进不去success方法的问题。格式错误)

    一,原理 1.1,解析1 将字符串解析为JavaScript代码,比如:var a = "alert('a');";这里的a就只是一个字符串而已,输出的话也是alert(a);这句 ...

  10. 资料--Linux开发

    <Linux/UNIX系统编程手册>凯利斯克 (Michael Kerrisk) <UNIX环境高级编程>(第2版),史蒂文斯著 <深入理解 Linux 内核>(第 ...