本书从根本上展示了generic patterns(泛型模式)或pattern templates(模式模板),并将它们视之为“在C++中创造可扩充设计”的一种功能强大的新方法。这种方法结合了template和patterns,你可能未曾想过,但的确存在。为C++打开了全新视野,而且不仅仅在编程方面,还在于软件设计本身;对软件分析和软件体系结构来说,它也具有丰富的内涵。
译序by 候捷\r\n译序by 於春景\r\n目录\r\n序言 by Scott Meyers\r\n序言 by John Vlissides\r\n前言\r\n致谢\r\n第一篇 技术(Techniques)\r\n第1章 基于Policy的Class设计(Policy-Based Class Design)\r\n第2章 技术(Techniques)\r\n第3章 Typelists\r\n第4章 小型对象分配技术(Small-Object Allocation)\r\n第二篇 组件(Components)\r\n第5章 泛化仿函数(Generalized Functors)\r\n第6章 Singletons(单件)实作技术\r\n第7章 Smart Pointers(智能指针)\r\n第8章 Object Factories(对象工厂)\r\n第9章 Abstract Factory(抽象工厂)\r\n第10章Visitor(访问者、视察者)\r\n第11章 Multimethods\r\n附录 一个超迷你的多线程程序库(A Minimalist Multithreding Library)\r\n参考书目(Bibliography)\r\n索引(Index)
也许你正在书店里捧着这本书,问自己该不该买下它。或者,你正在公司的图书室里,犹豫该不该花时间阅读它。我知道你时间宝贵,所以我开门见山。如果你曾经问过自己:如何撰写更高级的C++ 程序?如何应付即使在很干净的设计中仍然像雪崩一样发生的不相干细节?如何构建可复用组件,使得每次将这些组件应用到下一个程序时都无需对它们大动干戈?如果你曾这样问过自己,那么,本书正是为你所写。
想象这样的情景。你刚从一次设计会议回来,带着一些打印图表,上面有你潦草写下的注解。哦,对象之间传递的事件型别(event type)不再是char而是int了,于是你修改一行代码。指向Widget的smart pointers太慢了,得取消一些检查措施,让它们快一点,于是你又修改一行代码。另一个部门刚才添加Gadget class,你的object factory必须支持它,于是你再次改动一行代码。
你修改了这个设计。编译,链接,搞定。
且慢,场景有点问题,不是吗?现实情形更可能是:你匆匆从会议中赶回来,因为有一大堆工作要做。于是你开始地毯式搜索,并在代码上大动干戈:添加新的代码、引入臭虫、消除臭虫…,这就是程序员的生活不是吗?本书也许不能保证你实现第一场景,但它朝着那个方向迈出坚实的一步。它对软件设计师展示的C++,宛如一种新语言。
传统上,代码是软件系统中最琐碎。最复杂的环节。尽管历史上出现了各种层次的编程语言,支持各种设计方法(譬如面向对象方法),但在蓝图和代码之间,总是横亘着一条鸿沟。这是因为,代码必须仔细关照具体实现和某些辅助性任务中极其细节的问题。因此,设计意图往往被无尽的细节吞噬。
本书提供了一组可复用的设计产品 ─ 所谓“泛型组件”,以及设计这些组件所需要的技术。这些泛型组件为用户带来的明显好处,集中于程序库方面,而处于更广泛的系统体系结构空间中。本书提供的编程技术和实作品(implementation)所反映的任务和议题,传统上落于设计范畴之中,是编写代码之前必须完成的东西。由于身处较高层次,泛型组件就有可能以一种不同寻常但简洁。易于表达。易于维护的方式,将复杂的体系结构反映到代码中。
这里结合了三个要素:设计模式(design patterns)、泛型编程(generic programming)、C++。结合这些要素后,我们获得极高层次的可复用性,无论是横向或纵向。从横向空间来看,少量library code就可以实现组合性的、实质上具有无穷数量的结构和行为。从横向空间来看,由于这些组件的通用性,它们可广泛应用于各种程序中。
本书极大归功于设计模式(design patterns)— 面临面向对象程序开发中的常见问题时,它是强有力的解决方案。设计模式是经过提炼的出色设计方法,对于很多情况下碰到的问题,它都是合理而可复用的解决方案。设计模式致力于提供深具启发、易于表达和传递的设计词汇。它们所描述的,除了问题(problem)之外,还有久经考验的解法及其变化形式,以及选择每一种方案所带来的后果。设计模式超越了任何一种设计语言所能表达的东西 ─ 无论那种语言多么高级。本书遵循并结合某些设计模式,提供的组件可以解决广泛的具体问题。
泛型编程是一种典范(paradigm),专注于将型别(type)抽象化,形成功能需求方面的一个精细集合,并利用这些需求来实现算法。由于算法为其所操作的型别定义了严格、精细的接口,因此相同的算法可以运用于广泛的型别集(a wide collection of types)。本书提供的实作品采取泛型编程技术,以最小代价获得足以和手工精心编写的代码相匹敌的专用性。高度简洁和效率。
C++ 是本书使用的唯一工具。在本书中,你不会看到漂亮的窗口系统。复杂的网络程序库或灵巧的日志记录(logging)机制。相反的,你会发现很多基础组件,这些组件易于实现以上所有系统(甚至更多)。C++ 具有实现这一切所需要的广度,其底层的C内存模型保证了最原始效率(raw performance),对多态(polymorphism)的支持成就了面向对象技术,templates则展现为一种令人难以置信的代码生成器。Templates遍及本书所有代码,因为它们可以令用户和程序库之间保持最密切的协作。在遵循程序库约束的基础上,程序库的用户可以完全控制代码的生成方式。泛型组件库的角色在于,它可以让用户指定的型别和行为,与泛型组件结合起来,形成合理的设计。由于所采技术之静态特性,在结合和匹配相应组件时,产生的错误通常在编译期便得以发现。
本书最明显的意图在于创建泛型组件,这些组件预先实现了设计模块,主要特点是灵活、通用、易用、泛型组件并不构成framework。实际上它们采用的作法是互补性的,虽然framework定义了独立的classes,用来支持特定的对象模型,但泛型组件(s) 是轻量级设计工具,互相独立,可自由组合和匹配。实现frameworks时泛型组件可带来很大帮助。
本书读者
本书预定的读者主要分为两类。第一类是富有经验的C++ 程序员,他们希望经由本书掌握最先进的程序库编写技术。本书提供了新而强大的C++ 技术,这些技术具有惊人能力,有一些甚至令人匪夷所思。这些技术对于撰写高级程序库极有帮助。当然,希望更上层楼的中阶C++程序员也会发现本书十分有益,特别是如果他们愿意付出一些毅力。本书虽然有时给出一些高难度的C++ 代码,但都有详尽说明。
本书预定的第二类读者是繁忙的程序员,他们需要完成工作,但无法投入时间进行深入学习。他们可以快速略过最复杂的细节,把注意力放在如何使用本书提供的程序库上。每一章都有一个导入说明,并以概览(Quick Facts)结束。程序员们会发现这种安排方式为理解和使用本书组件提供了有益的参考。这些组件可以分开理解,它们功能强大但很安全,而且让人乐于使用。
你需要扎实的C++ 经验,以及强烈的求知欲。你也需要对templates和STL(Standard Template Library)有一定的掌握。
如果你已经了解design patterns(Gamma等著,1995),那当然好,但并非必要。书中对于用到的patterns和idioms(惯用手法)都有详细介绍。本书并不是patterns方面的专著,并不试图完整阐述patterns。由于patterns是程序库设计者从实践的角度提出的,所以即使那些曾经关注patterns的读者也会发现,他们的视野如今有了更新 — 如果他们曾经受到束缚的话。
Loki
本书讲述一个实际的C++ 程序库,称为Loki。Loki是挪威神话中的智慧之神,同时也是一个淘气鬼,作者希望,这个程序库的创意和灵活会让你想起那个有趣的挪威神话人物。程序库中的所有元素都位于名字空间(namespace)Loki之内,此一名称并未出现于书中范例程序上,因为那会为代码带来非必要的缩排格式,并增加代码的数量。Loki是免费的,你可以从http://www.awl.com/cseng/titles/0-201-70431-5下载它。
除了线程(threading)部分,Loki完全以标准C++ 写成。唉,这也意味目前很多编译器无法处理其中某些部份。我在Metrowerks Code Warrior Pro 6.0和Comeau C++ 4.2.38上实作并测试Loki,并且都在Windows平台上。KAI C++ 处理Loki代码好象也没有问题。随着供应商逐渐发行更新更好的编译器,你将能够运用Loki提供的所有功能。
本书提供的Loki代码和范例采用了一种很普及的写码标准,这一标准最早由Herb Sutter倡导。我相信你很快便能适应它。简单地说:
* classes、functions、枚举型别(enumerated type)看起来像LikeThis。
(译注:由于版面上的需要,中译本的functions看起来像LikeThis)
* 变量和枚举值看起来像likeThis。
* 成员变量看起来如likeThis_。
* template参数如果只可能是用户自定型别,那么它会被声明为class,如果还可能是基本型别,那么它会被声明为typename。
内容组织
本书由两大篇组成:技术篇和组件篇。第一篇(1~4章)讲述的是,在泛型编程中 — 特别是在泛型组件的构造中 — 所运用的C++ 技术。它展示了与C++ 相关的大量功能和技术:policy-based设计、partial template specialization、typelists、local classes等等。你可以按部就班地阅读本篇,然后回过头来参考特定章节。
第二篇建立在第一篇的基础上,实作出多个泛型组件。这些并非纸上谈兵,他们是具有工业强度的组件,可应用于现实世界的应用程序中。C++ 开发者在日常工作中经常遇到的议题,例如smart pointers、object factories、functor objects,在此都有深入的探讨,并提供泛型实作。文中提供的实作品满足了基本需要,解决了基本问题。本书并不讲述这一块那一块代码做些什么,它采行的方法是:讨论问题,选择设计决策,然后逐步实现这些设计决策。
第1章提供的是policies,一种有助于产生灵活设计的C++ 技巧。
第2章讨论和泛型编程有关的通用C++ 技巧。
第3章实作typelists,一种功能强大、用于操纵型别的数据结构。
第4章介绍一个重要的辅助工具:小型对象分配器。
第5章介绍泛化仿函数的概念,在运用Command模式的设计中,它很有用处。
第6章讲述Singleton对象。
第7章讨论和实现了Smart Pointers。
第8章讲述generic Object Factories。
第9章探讨Abstract Factory设计模式,并提供一份实作品。
第10章以泛型方式实现了Visitor设计模式的几个变型。
第11章实现了数个MutiMethod引擎,这些方案体现设计上的各种选择。
“设计”涵盖许多重要工作,C++ 程序员必须以规律的、标准的、合格的基础和准则来对付。我个人认为Object Factories(第8章)是所有高品质多态设计(polymorphic design)的基石。Smart Pointers(第7章)是大大小小许多C++ 应用程序的重要组件。Generalized Functors(第5章)有极为宽广的应用,一旦你拥有它,许多复杂的设计问题都能够迎刃而解。其他更特殊的泛型组件,例如Visitor(第10章)或MultiMethod(第11章),也都有重要而合适的应用,并将语言的支持推向极致。