《C++ Templates》第一章 关于本书

类别:编程语言 点击:0 评论:0 推荐:

  尽管模板成为C++的一部分已经十年有余了(几乎在同样长的时间里,它以各种不同的形式被使用着),然而,模板仍然会导致误解,误用或争论。同时,人们也日益发现它是开发出更清晰,快捷和智能的软件的强大工具。事实上,模板已经成为几种新的C++编程典范(paradigm)的基石。

 

  同时我们也发现大部分书籍和文章对C++模板理论和应用最多只是肤浅地对待。即便是那些为数甚少的,对基于模板的各种技术作出极好的考察的书籍也都没有精确的描述出语言是如何支持这些技术的。因此,无论是初级的还是高级的C++程序员都有这样的感觉:试图去弄明白”为什么自己的代码会以意想不到的方式被处理”就好象是在跟模板角力。

 

  这些就是我们写这本书的主要动机。然而,我们独立的计划了这个主题,并且,关于使用何种途径(去表现该主题),我们的想法稍微有些不同:

 

David的目标是对于C++模板的语言机制以及它所支持的(主要的和重要的)高级编程技术提供一个完全的参考。他将目标集中在精确性和完备性上。

Nico的兴趣是让这本书成为一本帮助他自己和其他程序员使用模板的书。这意味着当涉及到模板的一些比较实际的方面时,这本书应该将材料以一个比较直观的方式呈现出来。

 

  从某种意义上,你可以将我们看成是一个科研人员和一个工程师:我们有同样的原则和目的,只是我们强调的有所不同(当然,也有很多相同之处)。

 

  Addison-Wesley使我们走到了一起,所以,你就看到了现在的这本书—一本关于C++模板的详细指南和参考。这本书不仅包含了对语言基础的介绍,还将目标放在提高对”能够通向实际解决方案的设计方法”的感知上。同样,这本书并不仅仅是一本关于C++模板语法和语义的细节的参考,还是一本关于被广泛了解的和较少有人了解的惯用手法和技术的介绍。

 

 

1.1 在阅读本书之前你应该知道的(What You Should Know Before Reading This Book)

 

  为了能从树中获得最多的知识,你应该首先了解C++:我们描述的是关于一个特定的语言特性的细节,并非语言自身的基础。你应该对类和继承的概念很熟悉,并且能够使用C++标准库里面的组件(诸如iostream,容器等)写C++程序。另外,随着需要的增多,我们会回顾更多微妙的问题,甚至这些问题可能与模板并没有直接关系。然而这样我们就能确保这本书的内容对于专家级的和中级的程序员都是可接受的。

 

  我们主要涉及在1998年被标准化的C++语言(见[Standard98]),还有C++标准委员会在它的第一次技术勘误(见[Standard02])中的意见。如果你觉得自己对C++基础的理解是不正确的或是过时的,我们建议你先看看[StroustrupC++PL],[JosuttisOOP]和[JosuttisStdLib]以更新你的C++知识。这些书是对现代C++语言和标准库的极好的介绍。其他出版物列在附录B.3.5。

 

 

1.2 本书的大体结构(Overall Structure of the Book)

 

  我们的目标是提供以下信息:关于如何开始使用模板并从其强大能力中获益,并使有经验的程序员达到更高境界。为此,我们决定将本书组织为若干部分:

 

Part I 介绍有关模板的最基本的概念。这一部分以”指南”的风格来写。

Part II 展示了语言细节,并且提供了一份有关模板的便捷的参考。

PartIII 解释了C++模板所支持的基本的设计技术—从一些细小的点子到被广泛使用的惯用手法—在其他书上可能这些从未出现过。

PartIV 建立在前面两个部分的基础上,并且加入了有关模板的各种普遍应用的讨论。

 

  每一个部分都包含若干章节。此外,我们还提供了一些附录—包含一些并非只与模板有关的材料(例如,有关C++重载决议的全面阐述)。

 

  第一部分的各章应该顺序阅读,例如,第三章的内容建立在第二章的材料的基础上。而对于其他部分,各章之间则几乎没有联系,例如,先阅读二十二章(关于仿函数)后阅读二十章(关于智能指针)是完全正常的。

 

  最后,如果你不想按顺序阅读本书,我们还提供了一个相当完备的索引。

 

1.3 如何阅读本书(How to Read This Book)

 

  如果你是一个想要学习或是回顾模板的概念的C++程序员,请仔细阅读第一部分—The Basics。即使你已经对模板非常熟悉,对该部分作一个快速的浏览也能够帮助你熟悉我们所使用的风格和术语。这一部分也包括关于包含模板的代码的逻辑组织方式。

 

  根据你比较喜爱的学习方式,你可能会决定专心研读第二部分关于模板的细节,也可能先阅读第三部分的实际编码技术(然后再回过头去看第二部分的更为微妙的语言问题)。

 

  如果你将本书和日常遇到的编程挑战结合到一起,则后者的阅读方式可能比较具有实际用处。第四部分和第三部分有些相似,但是更着重于理解模板如何在特定应用中(而不是设计技术中)发挥作用。因此,在阅读第四部分之前,你最好先熟悉第三部分的主题。

 

  附录包括许多有用的信息,并且在书中经常会提到这些信息。我们努力使这些信息成为有趣的(它们本身的意义也决定了这一点)。

 

  根据我们的经验,学习新东西的最好的方式是通过例子。因此,在全书中你会发现许多例子。有些只是几行用于阐明某个抽象概念的代码,而另一些则是提供了(有关某种技术的 )具体应用的完整程序。后者会在代码前注名它所来自的文件。你可以在本书的网站(http://www.josuttis.com/tmplbook/)上找到这些文件。

 

1.4 关于编程风格的一些注意点(Some Remarks About Programming Style)

 

  C++程序员们(包括我们)使用不同的编程风格:于是诸如”将空格,分隔符(大括号,圆括号)放在那里”这种问题就出现了。通常我们总是试图保持一致,尽管我们有时候会因为主题而作出让步。例如,在本书的前面部分,我们可能比较喜欢使用空格和含义丰富的长名字以使代码更为清楚明了,然而,在后面更进一步的讨论中,使用较紧凑的格式可能更为恰当。

 

  关于类型,参数和变量的声明,我们作出了一个有些不寻常的决定。很明显,有几种可行的风格:

 

void foo (const int &x);  //注意’&’号的位置

void foo (const int& x);

void foo (int const &x);

void foo (int const& x);

 

  我们决定使用 int const这种风格(而不是const int(常量整数)),尽管这有些不寻常。有两点理由:第一,这种风格很好的回答了”什么是常数性质的?”这个问题—“位于const修饰符前面的”才是常数性质的。事实上,尽管

 

const int N=100;

  与

int const N=100;

  等价。然而对于

int* const bookmark; //the point cannot change,but the value

//pointed to can change

 

  却没有等价格式(将’const’放到’*’前面(或’int’前面)就改变了它的意义)。在这个例子中,具有常量性质的是指针,而不是指针所指的int。

 

  我们的第二个原因与一个语法置换规则有关(该规则在涉及到模板时被普遍用到)。考虑以下两个typedef[1]:

 

typedef char* CHARS;

typedef CHARS const CPTR; //constant pointer to chars

 

  如果我们将CHARS所代表的东西原样照搬到第二个typedef中,则第二个typedef意义不变:

 

typedef char* const CPTR; //constant pointer to chars

  然而,如果我们将const写在类型名之前,这个原则就不适用了。事实上,考虑以上例子的另一种可能的选择:

 

typedef char* CHARS;

typedef const CHARS CPTR;  //const pointer to chars

 

  这时,如果仍然将CHARS原样替换掉,则第二行代码的意思就变得截然不同了:

 

typedef const char* CPTR;  //point to constant chars

 

  当然,对于volatile修饰符同样可以这样考虑。

 

  关于空格,我们决定将空格放在’&’号和参数名称之间:

 

void foo(int const&  x);

 

  这样,我们就能突现出参数类型和参数名称是分隔开的。无可否认,这样作会导致类似以下的声明更容易让人产生混淆:

 

char*  a, b;

 

  根据从C语言继承来的规则,a是一个指针而b却是个普通的char。为了避免这种混淆,我们只要简单的避免这种声明方式。

 

  这不是一本关于C++标准库的书,但是我们在例子中使用了标准库。通常,我们使用特定与C++的头文件(例如,<iostream>而不是<stdio.h>)。<stddef.h>是个例外。我们使用<stddef.h>而非<cstddef>,这样就不需要在size_t和ptrdiff_t前面加上std::前缀,因为这同样是可移植的,并且使用std::size_t并不比使用size_t有更大的优势。

 

 

1.5 标准vs现实(The Standard versus Reality)

 

  C++标准在1998年末就开始生效。然而,直到2002年才有编译器能够声明”完全支持标准”。因此,编译器在对语言的支持方面仍然参差不齐。有些编译器能够编译本书中的大部分代码,但是还有一些相当流行的编译器不能处理本书中的许多例子。因此,对于那些不合标准的C++实现,我们常常要引入另外一种技术来修补我们的例子,以期提供一个完整的或部分的解决方案,但是有些技术目前还在它们的能力之外。我们希望,随着程序员们要求他们的编译器供应商提供对标准的支持,这些问题会被很大程度上解决。

 

  即便是这样,C++语言仍然会随着时间的推移而不断演化。目前已经是C++社团中的专家们(不管他们是否加入了C++标准委员会)一直在讨论改进C++语言的方法,并且有一些候选方案涉及到模板。第十三章展示了这个方面的一些趋势。

 

1.6 示例代码和附加信息(Example Code and Additional Informations)

 

  你可以得到所有的示例程序,并且在本书的网站上找到关于本书的更多的信息,网址如下:

    http://www.josuttis.com/tmplbook/

  你也可以在David Vandevoorde的网站上找到许多关于这个主题的其他信息。David的网站网址如下:

http://www.vandevoorde.com/Templates

  449页还列出了本书所有的参考书目。

 

1.7 读者回应(Feedback)

 

  我们欢迎你给我们提出建设性的建议—无论是正面的还是反面的。我们努力使这本书成为一本优秀的书。然而,最终我们得停止写作,回顾,和整理,这样我们才能出版本书。因此你可能会在本书中找到错误,不一致,或可以改进的地方,或者缺少某个主题。你的回应会在我们的网站上列出来以告知所有的读者,并且使本书的后续版本更为完善。

  联系我们最好的方式是e-mail:

[email protected]

  在发送你的回应之前别忘了看看网站上已有的勘误。

  非常感谢。

[1] 注意,在C++中,一个typedef定义了一个”类型别名”,而并非一个新的类型。例如:

typedef int Length;  //define Length as an alias for int

int i=42;

Length l=88;

i=l;  //OK

l=i;  //OK

 

本文地址:http://com.8s8s.com/it/it28395.htm