C++实践系列C++中的模板(template)
- 格式:doc
- 大小:43.50 KB
- 文档页数:8
1.MFC概述1.MFC是一个编程框架MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。
因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。
Microsoft Visual C++提供了相应的工具来完成这个工作:AppWizard可以用来生成初步的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用户接口;ClassWizard用来协助添加代码到框架文件;最后,编译,则通过类库实现了应用程序特定的逻辑。
1.封装构成MFC框架的是MFC类库。
MFC类库是C++类库。
这些类或者封装了Win32应用程序编程接口,或者封装了应用程序的概念,或者封装了OLE特性,或者封装了ODBC和DAO数据访问的功能,等等,分述如下。
(1)对Win32应用程序编程接口的封装用一个C++ Object来包装一个Windows Object。
例如:classCWnd是一个C++ window object,它把Windows window(HWND)和Windows window有关的API函数封装在C++ windowobject的成员函数内,后者的成员变量m_hWnd就是前者的窗口句柄。
(2)对应用程序概念的封装使用SDK编写Windows应用程序时,总要定义窗口过程,登记Windows Class,创建窗口,等等。
MFC把许多类似的处理封装起来,替程序员完成这些工作。
另外,MFC提出了以文档-视图为中心的编程模式,MFC类库封装了对它的支持。
文档是用户操作的数据对象,视图是数据操作的窗口,用户通过它处理、查看数据。
(3)对COM/OLE特性的封装OLE建立在COM模型之上,由于支持OLE的应用程序必须实现一系列的接口(Interface),因而相当繁琐。
第1篇一、引言随着计算机科学的不断发展,数据结构作为计算机科学的基础学科,其重要性日益凸显。
为了提高我们对数据结构理论知识的理解和应用能力,我们开展了为期一个月的数据结构本科实践活动。
本次实践活动旨在通过实际操作,加深对数据结构理论的理解,提高编程能力和问题解决能力。
以下是本次实践活动的详细报告。
二、实践目的与内容1. 实践目的(1)巩固和深化对数据结构基本概念和原理的理解;(2)提高编程能力和问题解决能力;(3)培养团队合作精神,提高团队协作能力;(4)熟悉常见数据结构的实现和应用。
2. 实践内容本次实践活动主要包括以下内容:(1)选择合适的数据结构,如线性表、栈、队列、链表、树、图等;(2)实现这些数据结构的基本操作,如插入、删除、查找、遍历等;(3)分析各种数据结构的性能特点,对比其优缺点;(4)结合实际应用场景,设计并实现相关算法。
三、实践过程1. 线性表首先,我们选择了线性表作为实践的第一步。
线性表是一种基本的数据结构,它由一系列元素组成,元素之间存在一对一的线性关系。
我们实现了线性表的基本操作,包括插入、删除、查找和遍历。
在实现过程中,我们使用了数组作为存储结构,并分析了其时间复杂度和空间复杂度。
2. 栈与队列接着,我们学习了栈和队列这两种特殊的线性表。
栈是一种后进先出(LIFO)的数据结构,而队列是一种先进先出(FIFO)的数据结构。
我们分别实现了栈和队列的基本操作,并通过具体实例展示了它们在实际应用中的优势。
3. 链表链表是一种更为灵活的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
我们实现了链表的基本操作,包括插入、删除、查找和遍历。
通过链表的学习,我们加深了对指针的理解,并掌握了动态内存分配的技巧。
4. 树与图在掌握了线性表和链表的基础上,我们进一步学习了树和图这两种非线性数据结构。
树是一种层次结构,它由根节点和若干子树组成;图则是一种由节点和边组成的数据结构,节点之间可以是任意关系。
MFC/VC++调用word进行报表制作使用word进行数据报告的制作可谓非常方便,word具有非常强大的编辑、排版功能。
使用word能够制作出内容丰富、样式精美的报告。
我们在工作中当然会有报表报告的需求,如果能够在MFC/VC++里面能够调用word进行word格式报告的自动生成,岂不是一件非常惬意的事情。
我在工作当中需要对大量的数据或者各种测试数据进行统计分析,最终的统计分析结果总归要汇总为一份报告,不管是内部使用也好还是外部提供给客户也好,一份内容翔实、格式精美的报告自然必不可少。
我对MFC/VC++也不是高手,只是业余爱好自己动动手做些东西。
自然,低于VC操作word可谓完全没有经验,在网络上面也查找了很多资料,都是些只言片语,不能真正的领略通过VC使用word的方法。
于是自己摸索了几个礼拜,可谓耗时甚长,劳心劳力啊。
MS的东西,封装的也太严实了,对于函数部分只有些许的简单介绍,往往看的云里雾里。
没有实践还是不行啊!体会自己的经历,虽然辛苦但也有收获。
不想其他朋友再继续走我走过的路,浪费时间、精力,故成文以共享。
废话少说,进入正题吧。
第一步,当然我们需要首先导入word需要的库。
通过ClassWizard->Add Class选择From a Type Library…定位需要的库文件导入。
本例应该使用C:/Program Files/Microsoft Office/OFFICE11/MSWORD.OLB,在这里尽可选择所有的类导入,反正用的时候都有了,呵呵。
完成这一步,我们得到两个文件msword.h和msword.cpp,那就加入你的工程吧。
说明:如果需要在VC++/MFC开发程序操作word/excel等office元素,那么需要对必要的类型库进行导入.下面是office系列的类型库参考,导入类型库时候请选择正确的类型库进行导入.应用程序类型库Microsoft Access 97Msacc8.olbMicrosoft Jet Database 3.5DAO350.dllMicrosoft Binder 97Msbdr8.olbMicrosoft Excel 97Excel8.olbMicrosoft Graph 97Graph8.olb Microsoft Office 97Mso97.dll Microsoft Outlook 97Msoutl97.olb Microsoft PowerPoint 97Msppt8.olb Microsoft Word 97Msword8.olbMicrosoft Access 2000Msacc9.olb Microsoft Jet Database 3.51DAO360.dll Microsoft Binder 2000Msbdr9.olb Microsoft Excel 2000Excel9.olb Microsoft Graph 2000Graph9.olb Microsoft Office 2000Mso9.dll Microsoft Outlook 2000Msoutl9.olb Microsoft PowerPoint 2000Msppt9.olb Microsoft Word 2000Msword9.olbMicrosoft Access 2002Msacc.olb Microsoft Excel 2002Excel.exe Microsoft Graph 2002Graph.exe Microsoft Office 2002MSO.dll Microsoft Outlook 2002MSOutl.olb Microsoft PowerPoint 2002MSPpt.olbMicrosoft Word 2002MSWord.olbMicrosoft Office Access 2003Msacc.olbMicrosoft Office Excel 2003Excel.exeMicrosoft Office Graph 2003Graph.exeMicrosoft Office 2003MSO.dllMicrosoft Office Outlook 2003MSOutl.olbMicrosoft Office PowerPoint 2003MSPpt.olbMicrosoft Office Word 2003MSWord.olb注意:这些类型库的默认位置是:Office 版路径本Office 97C:/Program Files/Microsoft Office/OfficeC:/Program Files/Microsoft Office/OfficeOffice2000Office XP C:/Program Files/Microsoft Office/Office10OfficeC:/Program Files/Microsoft Office/Office112003Dao350.dll 和Dao360.dll 的默认位置是C:/Program Files/Common Files/Microsoft Shared/Dao。
stl标准模板库STL标准模板库。
STL(Standard Template Library)标准模板库是C++标准库的一部分,它提供了一系列的通用模板类和函数,用于实现常见的数据结构和算法。
STL的设计理念是基于泛型编程,通过模板来实现数据结构和算法,使得代码具有高度的通用性和可重用性。
STL包含了多种容器类、迭代器、算法和函数对象等组件,为C++程序的开发提供了丰富的工具和资源。
容器类是STL中最基本的组件之一,它提供了各种不同类型的数据结构,如vector、list、deque、set、map等。
这些容器类可以方便地存储和管理数据,使得程序员能够更加专注于算法的实现,而不必关心数据的存储和管理细节。
通过使用STL容器类,程序员可以快速地构建出复杂的数据结构,从而提高代码的可读性和可维护性。
除了容器类之外,STL还提供了丰富的算法和函数对象,用于对容器中的数据进行操作和处理。
这些算法包括了排序、查找、遍历、复制、删除等常见操作,可以大大简化程序员的工作。
此外,STL还引入了迭代器的概念,使得算法能够与容器类解耦,从而更加灵活地进行数据处理。
在STL中,迭代器是一种类似指针的对象,用于遍历容器中的元素。
STL提供了多种不同类型的迭代器,如输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器等。
这些迭代器可以适配不同类型的容器,使得算法能够在不同的数据结构上通用,从而提高了程序的灵活性和可扩展性。
STL的设计思想是将数据结构和算法进行有效地组织和封装,使得程序员能够更加高效地开发和维护代码。
通过STL,程序员可以避免重复造轮子的工作,而是直接使用标准库提供的通用组件,从而提高了代码的质量和效率。
此外,STL还为C++程序员提供了一种统一的编程风格和规范,使得代码更加易读和易懂。
总的来说,STL标准模板库是C++程序开发中不可或缺的重要组成部分,它为程序员提供了丰富的工具和资源,使得代码的开发和维护变得更加高效和简便。
实习鉴定表模板标准版5篇Practice appraisal form template Standard Edition汇报人:JinTai College实习鉴定表模板标准版5篇前言:报告是按照上级部署或工作计划,每完成一项任务,一般都要向上级写报告,反映工作中的基本情况、工作中取得的经验教训、存在的问题以及今后工作设想等,以取得上级领导部门的指导。
本文档根据申请报告内容要求展开说明,具有实践指导意义,便于学习和使用,本文档下载后内容可按需编辑修改及打印。
本文简要目录如下:【下载该文档后使用Word打开,按住键盘Ctrl键且鼠标单击目录内容即可跳转到对应篇章】1、篇章1:实习鉴定表样本标准版2、篇章2:实习鉴定表范本(标准版)3、篇章3:实习鉴定表文档4、篇章4:实习鉴定表样本(基础版)5、篇章5:实习鉴定表范文(2020版)篇章1:实习鉴定表样本标准版到某某学校实习以来,在实习指导老师和实习学校领导的帮助下,我能自觉学习邓小平理论和三个代表重要思想,坚持四项基本原则,保持和党中央思想政治上的高度一致。
注意遵守纪律,尊敬领导,积极要求进步。
在工作上,要勤勤恳恳,关心学生,服从学校安排,完成教学任务。
班主任工作,要注意以身作则,和学生和同事团结友爱。
教学上,要注意尝试新的教学方法,提高课堂教学质量,上课要得到学生对老师好评。
在生活上要自觉从严要求自己,艰苦朴素,遵纪守法,作风正派,各方面要表现好。
我决心在今后的工作学习中,继续努力,忠诚教育事业,为社会主义现代化建设,贡献自己的力量。
如果不是教学实习,也可仿照其他专业类型,触类旁通,写出好鉴定的。
>篇章2:实习鉴定表范本(标准版)【按住Ctrl键点此返回目录】1、自主学习工作后不再像在学校里学习那样,有老师,有作业,有考试,而是一切要自己主动去学去做。
只要你想学习,学习的机会还是很多的,老员工们从不吝惜自己的经验来指导你工作,让你少走弯路;集团公司、公司内部有各种各样的培训来提高自己,你所要作的只是甄别哪些是你需要了解的,哪些是你感兴趣的。
藏文文献输入手册藏文文献输入手册前言本手册是关于如何将藏文文献输入到电脑并制作成电脑文件。
如果仔细地遵循手册中描述的步骤,就可以把文献转化成能够长期保存的电脑版的藏文文献。
电脑版本的文献用途相当广泛:不仅可以把它转化成传统藏文经书或者现代书籍的样式,也可以做成光盘(CD)或者网页. 把藏文文献制作成电脑文件主要包括三个步骤:输入和校对编辑后的版本标注和格式本手册包含前两个步骤。
另一部单独的THL 手册涵盖第三项。
在过去的二十年间,随着电脑技术的发展,诸多藏文文献都制作成了电子文本。
但是,进行此项工作的随意性较大,未能达到最佳标准或利用到最好的技术。
由于以往用于藏文输入的技术大多都已被更新或淘汰,所输入的许多文献都不适合于长期保存。
其结果是,尽管花费了很多精力,现有的许多电子版还不如原有的印刷版可靠、稳定和应用性强。
解决这个问题是本手册的目标。
如果从一开始就能遵循下列原则,制作一个稳定而且可用性较强的电子版文献的过程并不困难:只使用功能完善的Unicode字体进行输入,如Tibetan Machine Uni。
电子文件的保存格式必须耐用,并且能够转化成其它印刷或电子文本的格式。
按照原稿输入文献,不需校订原稿中的错误,以便保存某个公认版本的真实面貌。
如果您想纠正该文献中的错误,那么,您必须按照我们的修改指南来做校订。
这样我们可以同时保存修改前的原稿和修改后的文本。
在您输入过程中,特别要注意按原稿输入每一个细节。
增加原稿中没有的内容,如多余空格等,是不允许的。
要输入原稿的页码和行数号。
不仅输入要认真细致,校对也要仔细。
一部电子文献假如有很多错误,就失去了使用的价值。
校对时,您应打印出输入的文本,并与原稿对比校对,而不应仅仅在电脑屏幕上校对。
我们希望这些规则能够对任何藏语文献的输入项目都有所帮助。
对于THL文献输入工作而言,这些规则并非可有可无,而是每一步都要必须遵循的。
第一步: 电脑准备过程本节讲述如何设置电脑字体、键盘输入法和文字处理软件,以便输入Tibetan Unicode字体.1. 字体请安装Unicode Tibetan 藏文字体。
django的template的使用
Django 的模板(template)是用于生成动态内容的重要部分。
以下是使用 Django 模板的一般步骤:
1. 创建模板文件:在项目的模板目录中创建 HTML 文件,通常使用`.html`或`.tpl`扩展名。
2. 定义模板变量:在视图函数中,使用`render`或其他类似的方法传递数据给模板。
这些数据将作为模板变量在模板中使用。
3. 使用模板语法:在模板文件中,使用 Django 的模板语法来引用和显示模板变量。
例如,使用`{{ variable }}`来显示变量的值。
4. 控制结构:Django 模板提供了一些控制结构,如条件语句`if`和循环`for`,以便在模板中实现逻辑。
5. 模板继承:可以使用模板继承来共享和重用模板的一部分,从而提高代码的可维护性。
6. 模板过滤器:Django 提供了一系列模板过滤器,可以对模板变量进行加工和转换。
7. 模板加载顺序:Django 会按照特定的顺序加载模板,你可以自定义模板的加载顺序。
8. 调试和错误处理:在开发过程中,可以使用 Django 的调试工具来查看模板渲染过程中的错误和变量值。
这只是使用 Django 模板的一个简要概述,实际使用中还需要了解更多的细节和最佳实践。
Django 的文档提供了详细的模板使用指南和示例,你可以查阅相关文档以获取更深入的了解。
如果你有具体的问题或需要更详细的解释,请随时告诉我,我将尽力帮助你。
《面向对象程序设计》实验指导书(新)《面向对象程序设计》实验指导书一、课程教学与实验教学计划学时比:48/16二、适用专业:信息管理与信息系统三、实验目的基本要求能够充分理解面向对象程序设计的思想和应用方法。
能够使用面向对象编程语言进行相应的程序设计和开发。
理解面向对象的基本思想、概念和特性以及面向对象的分析、建模、设计技术与方法。
掌握C++语言基本构成、类与对象、消息传递与函数、函数与运算符重载、继承性、多态性与虚拟函数、数据封装和隐藏及Windows 程序设计基础。
通过实验动手实践,使学生能够掌握面向对象程序设计的特征和基本思想,以及相应的具体实现和Windows程序设计基础知识。
四、实验内容实验一:循环控制(一)实验目的要求:熟悉VC++集成开发环境,学习使用控制台应用程序;创建工程,建立可执行文件并执行,观察结果。
掌握变量的声明和定义方法,掌握循环语句和条件语句的定义、作用和使用方法。
(二)实验设备:1.服务器;2.交换机;3.计算机。
(三)实验内容:1.编程求1!+2!+3!+4!+…+12!。
2.编程求所有的3位数素数,且该数是对称的。
所谓“对称”是指一个数,倒过来还是该数。
例如,375不是对称数,因为倒过来变成了573。
实验二:递归函数(一)实验目的要求:掌握函数的概念和使用方法,掌握递归函数的概念和使用方法。
(二)实验设备:1.服务器;2.交换机;3.计算机。
(三)实验内容:1.用递归函数来求1!+2!+3!+…+12!。
2.用递归的方法建立一个函数int fibonacci(int n),求Fibonacci数列中第n个数的值。
实验三:用气泡法排序(一)实验目的要求:掌握文件读写的方法,掌握递归函数的概念和使用方法。
(二)实验设备:1.服务器;2.交换机;3.计算机。
(三)实验内容:建立一个文件,文件中包含一系列数,用这些数构成一个数组,并按照数值,为这个数组从小到大排序,把排序结果输出到另一个文件中。
利用Cacti中监控锐捷交换机CPU利用率(图文)Cacti是网络监控的利器之一,Cacti对cisco的网络设备支持的很好,对多数非cisco网络设备的接口流量也能正常显示,但是对CPU利用率这样的数据Cacti提供的模板(Template)就无法正确显示了。
这是因为非cisco的设备的CPU的SNMP OID不是cisco的值。
本文将以锐捷S21系列交换机为例介绍如何在通过Cacti监控锐捷交换机的CPU利用率。
Cacit是通过SNMP协议,读设备的相关的OID的值,来显示网络设备的运行状况和流量。
首先、找到锐捷交换机CPU的SNMP OID。
方法可以通过MIB Browser来找,或者找厂家索取。
我找到的锐捷S21系列交换机CPU的5分钟SNMP OID是”.1.3.6.1.4.1.4881.1.1.10.2.36.1.1.3.0”(以后在介绍怎么通过MIB Brower来找)。
Cacti通过各类的模板(Templates)来实现Devices、Datasources和Graph。
主要需要新增2个模板:Data Template和Graph Template。
建议找类似的模板,复制后在编辑。
放上我做的Date Template和Graph Template。
图:Data Template我的Data Template 使用的是Cisco Route – 5 Minute CPU Usage 修改的。
参数说明:Internal Data Source Name :建议不要用原来的,方便后面Graph Template 里面Item 的选择。
OID :填写找到的OID 值。
图Grap Template我利用Cisco router 的CPU 的Grap Template 改的。
参数说明:Graph Item :Item # 1:更改该参数的Date Template ,如下图。
这样模板就做好了,如果网络中大量使用的是锐捷交换机,可以把这个模板加到某个Host Templates里面去,这样就不需要每次都手动选择。
C++中的模板(template) 作者:张笑猛
提交者:eastvc 发布日期:2003-11-22 14:36:25 原文出处:http://objects.nease.net/
网上我最喜欢的技术文章是类似某何君所著“CVS快速入门”或者“UML reference card”之类,简短扼要,可以非常快的领着你进入一个新天地。而对于比较长的文章我通常是将其保存到硬盘上,然后准备着“以后有时间”的时候再看,但它们通常的命运都是“闲坐说玄宗”,直到某一天在整理硬盘时将它们以“不知所云”入罪,一并删除。
这篇小文主要是针对刚刚接触模板概念的读者,希望能帮助读者学习模板的使用。为了避免本文也在诸公的硬盘上遭逢厄运,我决定写的短些。“以后有时间”的时候再补充些内容。
TOC 1. 简介 2. 语法 3. 使用技巧 3.1 语法检查 3.2 继承 3.3 静态成员 3.4 模板类的运用
4. 参考资料
1. 简介 模板是C++在90年代引进的一个新概念,原本是为了对容器类(container classes)的支持[1],但是现在模板产生的效果已经远非当初所能想象。
简单的讲,模板就是一种参数化(parameterized)的类或函数,也就是类的形态(成员、方法、布局等)或者函数的形态(参数、返回值等)可以被参数改变。更加神 奇的是这里所说的参数,不光是我们传统函数中所说的数值形式的参数,还可以是一种类型(实际上稍微有一些了解的人,更多的会注意到使用类型作为参数,而往往忽略使用数值作为参数的情况)。
举个常用的例子来解释也许模板就从你脑袋里的一个模糊的概念变成活生生的代码了:
在C语言中,如果我们要比较两个数的大小,常常会定义两个宏: #define min(a,b) ((a)>(b)?(b):(a)) #define max(a,b) ((a)>(b)?(a):(b))
这样你就可以在代码中: return min(10, 4); 或者: return min(5.3, 18.6); 这两个宏非常好用,但是在C++中,它们并不像在C中那样受欢迎。宏因为没有类型检查以及天生的不安全(例如如果代码写为min(a++, b--);则显然结果非你所愿),在C++中被inline函数替代。但是随着你将min/max改为函数,你立刻就会发现这个函数的局限性 —— 它不能处理你指定的类型以外的其它类型。例如你的min()声明为:
int min(int a, int b); 则它显然不能处理float类型的参数,但是原来的宏却可以很好的工作!你随后大概会想到函数重载,通过重载不同类型的min()函数,你仍然可以使大部分代码正常工作。实际上,C++对于这类可以抽象的算法,提供了更好的办法,就是模板:
template const T & min(const T & t1, const T & t2) { return t1>t2?t2:t1; }
这是一个模板函数的例子。在有了模板之后,你就又自由了,可以像原来在C语言中使用你的min宏一样来使用这个模板,例如:
return min(10,4); 也可以: return min(5.3, 18.6) 你发现了么?你获得了一个类型安全的、而又可以支持任意类型的min函数,它是否比min宏好呢?
当然上面这个例子只涉及了模板的一个方面,模板的作用远不只是用来替代宏。实际上,模板是泛化编程(Generic Programming)的基础。所谓的泛化编程,就是对抽象的算法的编程,泛化是指可以广泛的适用于不同的数据类型。例如我们上面提到的min算法。
2. 语法 你千万不要以为我真的要讲模板的语法,那太难为我了,我只是要说一下如何声明一个模板,如何定义一个模板以及常见的语法方面的问题。
template<> 是模板的标志,在<>中,是模板的参数部分。参数可以是类型,也可以是数值。例如:
template class Temp{ public: ... void print() { cout << t << endl; } private: T t_; };
在这个声明中,第一个参数是一个类型,第二个参数是一个数值。这里的数值,必须是一个常量。例如针对上面的声明:
Temp temp; // 合法 int i = 10; Temp temp; // 不合法
const int j = 10; Temp temp; // 合法
参数也可以有默认值: template ... 默认值的规则与函数的默认值一样,如果一个参数有默认值,则其后的每个参数都必须有默认值。
参数的名字在整个模板的作用域内有效,类型参数可以作为作用域内变量的类型(例如上例中的T t_),数值型参数可以参与计算,就象使用一个普通常数一样(例如上例中的cout << t << endl)。
模板有个值得注意的地方,就是它的声明方式。以前我一直认为模板的方法全部都是隐含为inline的,即使你没有将其声明为inline并将函数体放到了类声明以外。这是模板的声明方式给我的错觉,实际上并非如此。我们先来看看它的声明,一个作为接口出现在头文件中的模板类,其所有方法也都必须与类声明出现在一起。用通俗的话来说,就是模板类的函数体也必须出现在头文件中(当然如果这个模板只被一个C++程序文件使用,它当然也可以放在.cc中,但同样要求类声明与函数体必须出现在一起)。这种要求与inline的要求一样,因此我一度认为它们隐含都是inline的。但是在Thinking In C++[2]中,明确的提到了模板的non-inline function,就让我不得不改变自己的想法了。看来正确的理解应该是:与普通类一样,声明为inline的,或者虽然没有声明为inline但是函数体在类声明中的才是inline函数。
澄清了inline的问题候,我们再回头来看那些我们写的包含了模板类的丑陋的头文件,由于上面提到的语法要求,头文件中除了类接口之外,到处充斥着实现代码,对用户来说,十分的不可读。为了能像传统头文件一样,让用户尽量只看到接口,而不用看到实现方法,一般会将所有的方法实现部分,放在一个后缀为.i或者.inl的文件中,然后在模板类的头文件中包含这个.i或者.inl文件。例如:
// start of temp.h template class Temp{ public: void print(); };
#include "temp.inl" // end of temp.h
// start of temp.inl template void Temp::print() { ... } // end of temp.inl
通过这样的变通,即满足了语法的要求,也让头文件更加易读。模板函数也是一样。
普通的类中,也可以有模板方法,例如: class A{ public: template void print(const T& t) { ...} void dummy(); };
对于模板方法的要求与模板类的方法一样,也需要与类声明出现在一起。而这个类的其它方法,例如dummy(),则没有这样的要求。
3. 使用技巧 知道了上面所说的简单语法后,基本上就可以写出自己的模板了。但是在使用的时候还是有些技巧。
3.1 语法检查 对模板的语法检查有一部分被延迟到使用时刻(类被定义[3],或者函数被调用),而不是像普通的类或者函数在被编译器读到的时候就会进行语法检查。因此,如果一个模板没有被使用,则即使它包含了语法的错误,也会被编译器忽略,这是语法检查问题的第一个方面,这不常遇到,因为你写了一个模板就是为了使用它的,一般不会放在那里不用。与语法检查相关的另一个问题是你可以在模板中做一些假设。例如:
template class Temp{ public: Temp(const T & t): t_(t) {} void print() { t.print();} private: T t_; }; 在这个模板中,我假设了T这个类型是一个类,并且有一个print()方法(t.print())。我们在简介中的min模板中其实也作了同样的假设,即假设T重载了'>'操作符。
因为语法检查被延迟,编译器看到这个模板的时候,并不去关心T这个类型是否有print()方法,这些假设在模板被使用的时候才被编译器检查。只要定义中给出的类型满足假设,就可以通过编译。
之所以说“有一部分”语法检查被延迟,是因为有些基本的语法还是被编译器立即检查的。只有那些与模板参数相关的检查才会被推迟。如果你没有写class结束后的分号,编译器不会放过你的。
3.2 继承 模板类可以与普通的类一样有基类,也同样可以有派生类。它的基类和派生类既可以是模板类,也可以不是模板类。所有与继承相关的特点模板类也都具备。但仍然有一些值得注意的地方。
假设有如下类关系: template class A{ ... }; | +-- A aint; | +-- A adouble;
则aint和adouble并非A的派生类,甚至可以说根本不存在A这个类,只有A和A这两个类。这两个类没有共同的基类,因此不能通过类A来实现多态。如果希望对这两个类实现多态,正确的类层次应该是:
class Abase {...}; template class A: public Abase {...}; | +-- A aint; | +-- A adouble;
也就是说,在模板类之上增加一个抽象的基类,注意,这个抽象基类是一个普通类,而非模板。