第一章 关于本书
模板,作为C++中的一部分已经有了十几年之久(而且也以各种形式存在),但我们仍然会对它误解、误用甚至产生争论。同时,我们又发现模板可以作为一个工具,用来开发更加干净、更具效率、更加智能的软件。事实上,模板已经成为许多新的C++程序设计范例(paradigms)的基石。
然而,我们发现大部分关于C++模板的书籍和论文对模板理论和应用的介绍都是很肤浅的。即使是少数几本讨论各种模板设计技术的书籍,也未能准确地描述C++语言是如何支持这些模板技术的。于是,无论是C++的初级程序员还是高级程序员,都会发现模板总是令他们感到困惑,他们也期望能知道(涉及到模板的)代码为什么总是出乎意料地出错。
这种现象是我们编写这本书籍的主要原因。然而,即使同样是针对模板的话题,我们两人选择的落脚点又有所不同,写书的方式也带有差异:
• David的目的是为了给读者提供一份关于C++模板的语言机制和应用模板所获得的高级编程技术的完整参考。他更多地注重准确性和完整性。
• Nico的兴趣在于希望这本书可以帮助他自己和那些在日常中使用模板的程序员。这就意味着在介绍模板实用技术的时候,应该以一种很直观的方式来阐述这些内容。
就某种意义而言,你会发现我们是一对科学家—工程师组合:虽然面对的是同一个话题,但我们的着重点却有所不同(当然,肯定会有一些重叠)。
Addison-Wesley让我们两个人走到了一起,才有了这本(我们认为)带有详细参考的C++模板教程。该教程不仅介绍了模板的语言特性,更注重于阐述一些与实际应用相关的设计方法。也就是说,该书不仅是一本关于C++模板的语法和语义的详细参考,也是一份介绍广为人知(和少为人知)的模板用法和技术的概要。
1.1 阅读本书所需具备的知识
为了能够理解本书中的大部分知识,你应该熟悉C++:我们描述的是该语言的一个特性(即模板),而不是语言本身的基础知识。你应该熟悉类和继承的概念,并且能够使用诸如IOstream和容器等C++标准库组件来编写程序。另外,在有必要的时候我们还会谈到语言的一些复杂话题,即使这些话题和模板并没有直接的关联。所有的这些说明了这本书主要适合于C++的专家和中级程序员。
我们所采用的语言是1998年标准化的C++语言(见[Standard98]),以及C++标准委员会在它的首份技术勘误表(见[Standard02])中所提供的澄清说明。如果你觉得你所理解的C++基本概念已经有些过时,那么我们建议你阅读[SroustrupC++PL]、[JosuttisOOP]和[JosuttisStdLib]来更新你的知识;这些书对现今的C++语言及其标准库都有很好的介绍,另外的书籍可以参考附录B.3.5。
1.2 本书的整体结构
我们的目的有两方面:一方面是为了给那些刚刚开始使用模板的程序员提供必要的信息,让他们可以从使用模板中受益;另一方面是为那些经验丰富的程序员介绍一些深入的知识,使他们可以走在模板应用的前列。为了实现这个目的,我们将整本书组织如下:
• 第1部分介绍了模板的基本概念,以教程的风格来介绍这些基本概念。
• 第2部分阐述了模板的语言细节,可以作为基于模板的构造的参考。
• 第3部分介绍了C++模板所支持的基本设计技术,覆盖的范围从微小的概念到复杂的用法;一些技术在别的书籍中都没有出现过。
• 第4部分在前两部分的基础上,深入讨论了各种使用模板的普通应用程序。
每个部分都由几个章节组成。另外,我们还提供了一些附录,它们涉及的范围并不局限于模板(例如,对C++重载解析的概述)。
对第1部分的每一章,你最好是按顺序阅读。例如,第3章就是建立在第2章(的内容)的基础之上的。然而,在其他的部分,章与章之间的关联是比较松散的。你可以随意安排阅读顺序,譬如先阅读关于仿函数的第22章,接下来才阅读关于智能指针的第20章。
1.3 如何阅读本书
如果你是一个希望学习或者温习模板概念的C++程序员,那么你应该仔细阅读第1部分——基础。即使你已经对模板非常熟悉,我们还是建议你大概浏览一下第1部分,这样有助于你了解我们所使用的风格和术语。这一部分还介绍了:当遇到包含模板的源代码时,你应该如何(逻辑地)组织这些源代码。
根据自己的学习方法,你既可以深入理解第2部分的许多细节,也可以直接阅读第3部分所介绍的实用编码技术(然后才回到第2部分阅读一些复杂的语言话题)。如果你每天面对使用模板的压力,那么后一种阅读方法通常是相当有用的。第4部分和第3部分有些类似,但它主要注重于如何把模板技术应用到具体的应用程序中,而不仅仅在于设计技术。因此,在阅读第4部分之前,最好熟悉第3部分所介绍的一些话题。
附录部分包含了很多内容,在本书的正文中我们也经常引用这些内容。我们也根据它们(指附录的内容)的特点,尽量把它们写得浅显易懂。
就我们自己的经验而言,学习一种新事物最好的方法就是研习描述该事物的例子。因此,在整本书中你到处都会看到许多代码例子。某些例子只是用于阐明某个抽象概念的短短几行代码,其他的则是完整的程序,为你提供了一份原汁原味的应用程序。后一种例子通过C++注释来引入,注释中描述了包含程序代码的文件,你可以在本书的网站http://www.josuttis.com/tmplbook/找到所有的这些文件。
1.4 关于编程风格的一些说明
C++程序员的编程风格通常是互不相同的,我们也不例外:风格所涉及的问题包括在哪里加入分隔符、界定符(花括号、圆括号)等。我们会尽量保持一致的风格,但就当前的一些(特殊的)话题,偶尔也会有所例外。例如,在教程这一部分(第1部分),我们使用了大量的空格和具体的名称,是为了令代码更加形象;而在高级话题讨论部分(第4部分),我们就使用了比较紧凑的风格,这样显得更加适合话题的讨论。
关于“类型、参数、变量”的声明,我们希望你能注意一些稍微特殊的用法。显然,下面几种风格都是可能的:
void foo (const int &x);
void foo (const int& x);
void foo (int const &x);
void foo (int const& x);
对“常整数”而言,上面的几种用法虽然差别不大,但我们趋向于使用int const,而不使用const int。作出这个选择,主要有两个原因:首先,针对问题“什么是恒定不变的?”,int const提供了很容易理解的答案。实际上,“恒定不变部分”指的是const限定符前面的部分。例如,尽管
const int N = 100;
等价于:
int const N = 100;
但是对于:
int* const book mark; //指针不能改变,但指针指向的值可以改变
却没有相应的等价形式(就是说如果把const限定符放在运算符 * 的前面,与前者并不等价)。在这个例子中,我们只是说明了指针本身是个常量,而并没有说明这个int值(即指针指向的值)是个常量。
第2个原因涉及到使用模板时一个很常用的语法替换原则。考虑下面的两个类型定义 :
typedef char* CHARS;
typedef CHARS const CPTR; //指向char类型的常量指针
当我们用CHARS所代表的含义对它进行替换之后,第2个声明的含义是不变的:
typedef char* const CPTR; //仍然是指向char类型的常量指针
然而,如果我们把const放在它所限定的类型的前面,那么这个原则就不再适用了。针对我们前面给出的两个类型声明,考虑下面的替换代码:
typedef char* CHARS;
typedef const CHARS CPTR; //指向char类型的常量指针
但如果我们替换掉CHARS之后,第2个声明却会导致不同的含义:
typedef const char* CPTR; //指向常量char类型的指针
当然,同样的现象(规则)也适用于volatile限定符。
对于间隔符,我们决定在 & 符号和参数名称之间留出一个空格:
void foo (int const& x);
借助这种方法,我们同时也强调了:参数类型和参数名称是分离的。
显然,诸如下面的声明更容易令人混淆:
在C++中,类型定义只是定义了一个“类型别名”,而不是一个新的类型。例如:
typedef int Length; //定义Length 为int的别名
int i = 42;
Length l = 88;
i = l; //正确
l = i; //正确
char* a, b;
上面代码中,如果根据C语言的规则,a是一个指针,而b是一个char类型的普通变量。为了避免产生这种混淆,我们尽量不在同一个语句中声明多个实体。
虽然这并不是一本介绍C++标准库的书,但我们在很多例子中都会用到标准库。在很多情况下,我们都使用了C++的特定头文件(例如我们使用<iostream>,而不是<stdio.h>)。唯一的例外情况是<stddef.h>,我们趋向于使用这个头文件,而不使用<cstddef>,从而也就不用给size_t和ptrdiff_t添加std:: 名字空间限定;另外,<stddef.h>具有更好的可移植性;而且,使用std::size_t替换size_t并不能得到任何好处。
1.5 标准和现实
C++标准自从1998年下半年以后就已经存在了。然而,直到2002年,才有了第一个完全符合标准的C++编译器。也就是说,大多数编译器对语言的支持仍然有所差异。有几个编译器可以编译本书的大部分代码,但一些(常用的)编译器并不能编译本书的很多代码。于是,针对这些编译器的(子标准)实现,我们经常提供了一些代替的技术,以获得一份完整(或者局部)的解决方案,但某些代替技术仍然不能为这些编译器所支持。总之,我们期望通过全世界的程序员要求编译器开发商支持标准,从很大程度上解决这个问题。
即使处于这样的现状,但随着时间的推移,C++程序设计语言仍然会不断地发展。C++社团的专家们(也包括非C++标准委员会成员的专家)正在讨论改善语言的各种方法,其中有几种候选方法就是与模板相关的,我们在第13章讨论这些发展趋势。
1.6 代码例子和更多信息
通过本书的网站,你可以获得本书的所有例子程序和相关信息,网站的地址是:http://www.josuttis.com/tmplbook。
另外,在David Vandevoorde的网站http://www.vandevoorde.com/templates和一些别的网站也可以找到该书的一些信息。在本书后面的参考书目中我们给出了另外的一些可供查询的信息。
1.7 反馈
我们欢迎你向我们反馈书中的任何信息——包括正面的和负面的反馈。我们付出了很多的努力,希望可以给你带来一本很优秀的书。另外,我们的写作、审阅和修润必须告一段落,只有这样才能保证这本书出版。因此,如果你发现一些错误、不一致的地方、能够改进的陈述方式或者遗漏了某些话题,请给我们提供反馈信息,让我们能够通过网站告诉所有的读者,也能在接下来的重印中进行改正。
你可以通过E-mail联系我们:tmplbook@josuttis.com
但是在给我们写信之前,请确定你已经查看了网站上关于本书的勘误表。
衷心感谢!
| 回书目 上一节 下一节 |
|
||||
| · Linux——从菜鸟到高手 · 体验Visual Studio 200.. · SOA 面向服务架构 · CISSP认证成长之路 · 隐私保护技术探讨 · WCF开发基础 · 珊瑚虫QQ作者侵权案开庭 · SQL Server 2008/2005.. |
· 华为员工自杀频频拷问.. · 计算机网络维护入门 · 开源虚拟化技术Xen · 贝恩资本携手华为22亿.. · 如何优化IT 控制能耗 · VMware技术应用 · 打造安全服务器 · iSCSI应用与发展 |
|||
|
||||
| · iSCSI应用与发展 · SQL Server 2008/2005.. · SOA 面向服务架构 · SQL Server 2008/2005.. · iSCSI应用与发展 · RAID——磁盘阵列基础 · 中间件应用技术专题 · 病毒查杀专题 |
· 国际文档格式标准开战 · Linux防火墙 · 打造安全服务器 · Sniffer安全技术从入门.. · SOA 面向服务架构 · ADSL应用面面俱到 · 入侵防护系统(IPS)初探 · TCP/IP协议专题 |
|||
|
||||
| · iSCSI应用与发展 · 中间件应用技术专题 · SQL Server 2008/2005.. · SOA 面向服务架构 · iSCSI应用与发展 · RAID——磁盘阵列基础 · 身份认证技术 · 病毒查杀专题 |
· 清除流氓软件——51CTO.. · Sniffer安全技术从入门.. · SOA 面向服务架构 · 了解统一威胁管理(UTM).. · ADSL应用面面俱到 · ADSL应用面面俱到 · 反垃圾邮件技术应用 · TCP/IP协议专题 |
|||