Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1530646
  • 博文数量: 465
  • 博客积分: 8915
  • 博客等级: 中将
  • 技术积分: 6365
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-30 15:05
文章分类

全部博文(465)

文章存档

2017年(33)

2016年(2)

2015年(4)

2014年(29)

2013年(71)

2012年(148)

2011年(178)

分类: C/C++

2012-11-16 14:45:36

 

传世经典书丛

深度探索C++对象模型

[]Stanley B. Lippman (斯坦利·B.·李普曼) 

侯捷 

ISBN 978-7-121-14952-8

20121月出版

定价:69.00

16

356

宣传语:如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么本书正适合你

作者Lippman参与设计了全世界第一套C++编译程序cfront,这本书就是一位伟大的C++编译程序设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码中)和implicit(隐藏于程序代码背后)的C++语意。

本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得多么大的效率。Lippman澄清了那些关于C++额外负荷与复杂度的各种错误信息和迷思,但也指出其中某些成本和利益交换确实存在。他阐述了各式各样的实现模型,指出它们的进化之道及其本质因素。书中涵盖了C++对象模型的语意暗示,并指出这个模型是如何影响你的程序的。

对于C++底层机制感兴趣的读者,这必然是一本让你大呼过瘾的绝妙好书。

本立道生        

对于传统的结构化(sequential)语言,我们向来没有太多的疑惑,虽然在函数调用的背后,也有着堆栈建制、参数排列、返回地址、堆栈清除等等幕后机制,但函数调用是那么的自然而明显,好像只是夹带着一个包裹,从程序的某一个地点跳到另一个地点去执行。

但是对于面向对象(Object Oriented)语言,我们的疑惑就多了。究其因,这种语言的编译器为我们(程序员)做了太多的服务:构造函数、析构函数、虚拟函数、继承、多态……有时候它为我们合成出一些额外的函数(或运算符),有时候它又扩张我们所写的函数内容,放进更多的操作。有时候它还会为我们的objects加油添醋,放进一些奇妙的东西,使你面对sizeof的结果大惊失色。

我心里头一直有个疑惑:计算机程序最基础的形式,总是脱离不了一行一行的循序执行模式,为什么OO(面向对象)语言却能够自动完成这么多事情呢?另一个疑惑是,威力强大的polymorphism(多态),其底层机制究竟如何?

如果不了解编译器对我们所写的C++代码做了什么手脚,这些困惑永远解不开。

这本书解决了过去令我百思不解的诸多疑惑。我要向所有已具备C++多年程序设计经验的同好们大力推荐这本书。

这本书同时也是跃向组件软件(component-ware)基本精神的跳板。不管你想学习COMComponent Object Model)、CORBACommon Object Request Broker Architecture)或是SOMSystem Object Model),了解C++ Object Model,将使你更清楚软件组件(components)设计上的难点与运用之道。不但我自己在学习COM的道路上有此强烈的感受,Essential COM(《COM本质论》,侯捷译,碁峰1998)的作者Don Box也在他的书中推崇Lippman的这一本卓越的书籍。

是的,这当然不会是一本轻松的书籍。某些章节(例如34两章)可能给你立即的享受——享受于面对底层机制有所体会与掌控的快乐;某些章节(例如567三章)可能带给你短暂的痛苦——痛苦于艰难深涩、难以吞咽的内容。这些快乐与痛苦,其实就是我翻译此书时的心情写照。无论如何,我希望通过我的译笔,把这本难得的好书带到更多人面前,引领大家见识C++底层建设的技术之美。

侯捷  2011.10.20  于新竹

jjhou@ccca.nctu.edu.tw

请注意:本书特点,作者Lippman在其前言中有很详细的描述,我不再多言。翻译用词与心得,记录在第0章(译者的话)之中,对您或有导读之功。

请注意:原文本有大大小小约8090个笔误。有的无伤大雅,有的影响阅读顺畅甚巨(如前后文所用符号不一致、内文与图形所用符号不一致——甚至因而导致图片的文字解释不正确)。我已在第0章(译者的话)列出所有我找到的错误。此外,某些场合我还会在错误出现之处再加注,表示原文内容为何。这么做不是画蛇添足,也不为彰显什么。我知道有些读者拿着原文书和中译书对照着看,我把原书错误加注出来,可免读者怀疑是否我打错字或是译错了。另一方面也是为了文责自负…………万一Lippman是对的而J.J.Hou错了呢?!我虽有相当把握,但还是希望明白摊开来让读者检验。

 

本立道生(侯捷 译序)     III

目录       VII

前言(Stanley B. Lippman       XIII

0  导读(译者的话)       XXV

1  关于对象(Object Lessons       1

加上封装后的布局成本(Layout Costs for Adding Encapsulation 5

1.1 C++对象模式(The C++ Object Model  6

简单对象模型(A Simple Object Model  7

表格驱动对象模型(A Table-driven Object Model 8

C++对象模型(The C++ Object Model   9

对象模型如何影响程序(How the Object Model Effects Programs     13

1.2  关键词所带来的差异(A Keyword Distinction     15

关键词的困扰       16

策略性正确的structThe Politically Correct Struct      19

1.3  对象的差异(An Object Distinction       22

指针的类型(The Type of a Pointer 28

加上多态之后(Adding Polymorphism   29

2  构造函数语意学(The Semantics of Constructors   37

2.1  Default Constructor的构造操作  39

带有Default Constructor”Member Class Object    41

带有Default Constructor”Base Class     44

带有一个Virtual Function”Class    44

带有一个Virtual Base Class”Class 46

总结       47

2.2  Copy Constructor的构造操作     48

Default Memberwise Initialization 49

Bitwise Copy Semantics(位逐次拷贝)    51

不要Bitwise Copy Semantics    53

重新设定Virtual Table的指针     54

处理Virtual Base Class Subobject 57

2.3  程序转化语意学(Program Transformation Semantics 60

显式的初始化操作(Explicit Initialization     61

参数的初始化(Argument Initialization  62

返回值的初始化(Return Value Initialization 63

在使用者层面做优化(Optimization at the User Level  65

在编译器层面做优化(Optimization at the Compiler Level  66

Copy Constructor:要还是不要?       72

摘要       74

2.4  成员们的初始化队伍(Member Initialization List 74

3  Data语意学(The Semantics of Data       83

3.1  Data Member的绑定(The Binding of a Data Member 88

3.2  Data Member的布局(Data Member Layout  92

3.3  Data Member的存取    94

Static Data Members      95

Nonstatic Data Members       97

3.4 “继承Data Member   99

只要继承不要多态(Inheritance without Polymorphism       100

加上多态(Adding Polymorphism   107

多重继承(Multiple Inheritance      112

虚拟继承(Virtual Inheritance  116

3.5  对象成员的效率(Object Member Efficiency       124

3.6  指向Data Members的指针(Pointer to Data Members 129

指向Members的指针的效率问题    134

4  Function语意学(The Semantics of Function  139

4.1  Member的各种调用方式    140

Nonstatic Member Functions(非静态成员函数)     141

Virtual Member Functions(虚拟成员函数)     147

Static Member Functions(静态成员函数)       148

4.2  Virtual Member Functions(虚拟成员函数)    152

多重继承下的Virtual Functions   159

虚拟继承下的Virtual Functions   168

4.3  函数的效能   170

4.4  指向Member Function的指针(Pointer-to-Member Functions    174

支持指向Virtual Member Functions”的指针     176

在多重继承之下,指向Member Functions的指针    178

指向Member Functions之指针的效率    180

4.5  Inline Functions    182

形式参数(Formal Arguments  185

局部变量(Local Variables       186

5  构造、析构、拷贝语意学(Semantics of Construction,

Destruction, and Copy       191

纯虚函数的存在(Presence of a Pure Virtual Function  193

虚拟规格的存在(Presence of a Virtual Specification    194

虚拟规格中const的存在     195

重新考虑class的声明   195

5.1 “无继承情况下的对象构造  196

抽象数据类型(Abstract Data Type 198

为继承做准备       202

5.2  继承体系下的对象构造      206

虚拟继承(Virtual Inheritance  210

vptr初始化语意学(The Semantics of the vptr Initialization 213

5.3  对象复制语意学(Object Copy Semantics     219

5.4  对象的效能(Object Efficiency      225

5.5  析构语意学(Semantics of Destruction  231

6  执行期语意学(Runtime Semantics 237

6.1  对象的构造和析构(Object Construction and Destruction    240

全局对象(Global Objects       242

局部静态对象(Local Static Objects       247

对象数组(Array of Objects    250

Default Constructors和数组  252

6.2  newdelete运算符    254

针对数组的new语意   257

Placement Operator new的语意   263

6.3  临时性对象(Temporary Objects    267

临时性对象的迷思(神话、传说)    275

7  站在对象模型的尖端(On the Cusp of the Object Model      279

7.1  Template       280

Template实例化行为(Template Instantiation 281

Template的错误报告(Error Reporting within a Template    285

Template中的名称决议法(Name Resolution within a Template   289

Member Function的实例化行为(Member Function Instantiation       292

7.2  异常处理(Exception Handling      297

Exception Handling快速检阅      298

Exception Handling的支持     303

7.3  执行期类型识别(Runtime Type IdentificationRTTI 308

Type-Safe Downcast(保证安全的向下转换操作)   310

Type-Safe Dynamic Cast(保证安全的动态转换)    311

References并不是Pointers   313

Typeid运算符       314

7.4  效率有了,弹性呢?   318

动态共享函数库(Dynamic Shared Libraries  318

共享内存(Shared Memory     318

 

 

 

差不多有10年之久,我在贝尔实验室(Bell Laboratories)埋首于C++的实现任务。最初的工作是在cfront上面(Bjarne Stroustrup的第一个C++编译器),从1986年的1.1版到19919月的3.0版。然后移转到Simplifier(这是我们内部的命名),也就是Foundation项目中的C++对象模型部分。在Simplifier设计期间,我开始酝酿本书。

Foundation项目是什么?在 Bjarne 的领导下,贝尔实验室中的一个小组探索着以C++完成大规模程序设计时的种种问题的解决之道。Foundation项目是我们为了构建大系统而努力定义的一个新的开发模型(我们只使用C++,并不提供多重语言的解决方案)。这是个令人兴奋的工作,一方面是因为工作本身,一方面是因为工作伙伴:BjarneAndy KoenigRob MurrayMartin CarrollJudy WardSteve BuroffPeter Juhl,以及我自己。Barbara Moo管理我们这一群人(BjarneAndy除外)。Barbara Moo常说管理一个软件团队,就像放牧一群骄傲的猫。

我们把Foundation想象成一个核心,在那上面,其他人可以为使用者铺设一层真正的开发环境,把它整修为他们所期望的UNIXSmalltalk模型。私底下我们把它称为Grail(传说中耶稣最后晚餐所用的圣杯),人人都想要,但是从来没人找到过!

Grail使用一个由Rob Murray发展出来并命名为ALF的面向对象层次结构,提供一个永久的、以语意为基础的表现法。在Grail中,传统编译器被分解为数个各自分离的可执行文件。parser负责建立程序的ALF表现法。其他每一个组件(如type checkingsimplificationcode generation)以及工具(如browser)都在程序的一个ALF表现体上操作(并可能加以扩展)。Simplifier是编译器的一部分,处于type checkingcode generation之间。Simplifier 这个名称是由Bjarne所倡议的,它原本是cfront的一个阶段(phase)。

type checkingcode generation之间,Simplifier做什么事呢?它用来转换内部的程序表现。有三种转换风味是任何对象模型都需要的:

1.与编译器息息相关的转换(Implementation-dependent transformations

这是与特定编译器有关的转换。在ALF之下,这意味着我们所谓的“tentative”nodes。例如,当parser看到这个表达式:

fct();

它并不知道是否(a)这是一个函数调用操作,或者(b)这是overloaded call operatorclass object fct上的一种应用。默认情况下,这个式子所代表的是一个函数调用,但是当(b)的情况出现,Simplifier 就要重写并调换 call subtree

2.语言语意转换(Language semantics transformations

这包括constructor/destructor的合成和扩展、memberwise初始化、对于memberwise copy的支持、在程序代码中安插conversion operators、临时性对象,以及对constructor/destructor的调用。

3.程序代码和对象模型的转换(Code and object model transformations

这包括对virtual functionsvirtual base classinheritance的一般支持、newdelete运算符、class objects所组成的数组、local static class instances、带有非常量表达式(nonconstant expression)之global object的静态初始化操作。我对Simplifier所规划的一个目标是:提供一个对象模型体系,在其中,对象的实现是一个虚拟接口,支持各种对象模型。

最后两种类型的转换构成了本书的基础。这意味着本书是为编译器设计者而写的吗?不是,绝对不是!这本书是由一位编译器设计者针对中高级C++程序员所写的。隐藏在这本书背后的假设是,程序员如果了解C++对象模型,就可以写出比较没有错误倾向而且比较有效率的代码。

什么是C++对象模型

有两个概念可以解释C++对象模型:

1.    语言中直接支持面向对象程序设计的部分。

2.    对于各种支持的底层实现机制。

语言层面的支持,涵盖于我的C++ Primer一书以及其他许多C++书籍当中。至于第二个概念,则几乎不能够于目前任何读物中发现,只有[ELLIS90][STROUP94]勉强有一些蛛丝马迹。本书主要专注于C++对象模型的第二个概念。本书语言遵循C++委员会于1995冬季会议中通过的Standard C++草案(除了某些细节,这份草案应该能够反映出此语言的最终版本)。

C++对象模型的第一个概念是一种不变量。例如,C++ class的完整virtual functions在编译时期就固定下来了,程序员没有办法在执行期动态增加或取代其中的某一个。这使得虚拟调用操作得以快速地派送(dispatch)结果,付出的成本则是执行期的弹性。

对象模型的底层实现机制,在语言层面上是看不出来的——虽然对象模型的语意本身可以使得某些实现品(编译器)比其他实现品更接近自然。例如,virtual function calls,一般而言是通过一个表格(内含virtual functions地址)的索引而决议得知。一定要使用如此的 virtual table 吗?不,编译器可以自由引进其他任何变通做法。如果使用virtual table,那么其布局、存取方法、产生时机以及数百个细节也都必须决定下来,而所有决定也都由每一个实现品(编译器)自行取舍。不过,既然说到这里,我也必须明白告诉你,目前所有编译器对于virtual function的实现法都是使用各个class专属的virtual table,大小固定,并且在程序执行前就构造好了。

如果C++对象模型的底层机制并未标准化,那么你可能会问:何必探讨它呢?主要的理由是,我的经验告诉我,如果一个程序员了解底层实现模型,他就能够写出效率较高的代码,自信心也比较高。一个人不应该用猜的方式,或是等待某大师的宣判,才确定何时提供一个copy constructor而何时不需要。这类问题的解答应该来自于我们自身对对象模型的了解。

写本书的第二个理由是为了消除我们对于C++语言(及其对面向对象的支持)的各种错误认识。下面一段话节录自我收到的一封信,来信者希望将C++引进于其程序环境中:

我和一群人工作,他们过去不曾写过(或完全不熟悉)C++OO。其中一位工程师从1985就开始写C了,他非常强烈地认为C++只对那些user-type程序才好用,对server程序却不理想。他说如果要写一个快速而有效率的数据库引擎,应该使用C而非C++。他认为C++庞大又迟缓。

C++当然并不是天生地庞大又迟缓,但我发现这似乎成为C程序员的一个共识。然而,光是这么说并不足以使人信服,何况我又被认为是C++代言人。本书就是企图极尽可能地将各式各样的Object facilities(如inheritancevirtual functions、指向class members的指针……)所带来的额外负荷说个清楚。

除了我个人回答这封信外,我也把此信转寄给HPSteve Vinoski;先前我曾与他讨论过C++的效率问题。以下节录自他的回应:

过去数年我听过太多与你的同事类似的看法。许多情况下,这些看法是源于对C++事实真相的缺乏了解。在上周,我和一位朋友闲聊,他在一家IC制造厂服务,他说他们不使用C++,因为它在你的背后做事情。我连连追问,于是他说根据他的了解,C++调用malloc()free()而不让程序员知道。这当然不是真的。这是一种所谓的迷思与传说,引导出类似于你的同事的看法……

在抽象性和实际性之间找出平衡点,需要知识、经验以及许多思考。C++的使用需要付出许多心力,但是我的经验告诉我,这项投资的回报率相当高。

我喜欢把本书想象成是我对那一封读者来信的回答。是的,本书是一个知识陈列库,帮助大家去除围绕在C++四周的迷思与传说。

如果C++对象模型的底层机制会因为实现品(编译器)和时间的变动而不同,我如何能够对于任何特定主题提供一般化的讨论呢?静态初始化(Static initialization)可为此提供一个有趣的例子。

已知一个class X有着constructor,如下面所示:

 

class X

{

  friend istream&

    operator>>( istream&, X& );

public:

  X( int sz = 1024 ) { ptr = new char[ sz ]; }

  ...

private:

  char *ptr;

};

 

而一个class Xglobal object的声明,如下面所示:

 

X buf;

 

int main()

{

  // buf 必须在这个时候构造起来

  cin >> setw( 1024 ) >> buf;

  ...

}

 

C++对象模型保证,X constructor将在main()之前便把buf初始化。然而它并没有说明这是如何办到的。答案是所谓的静态初始化(static initialization),实际做法则有赖开发环境对此的支持属于哪一层级。

原始的cfront实现品不单只是假想没有环境支持,它也假想没有明确的目标平台。唯一能够假想的平台就是UNIX及其衍化的一些变体。我们的解决之道也因此只专注在UNIX身上:我们使用nm命令。CC命令(一个UNIX shell script)产生出一个可执行文件,然后我们把nm施行于其上,产生出一个新的.c文件。然后编译这个新的.c文件,再重新链接出一个可执行文件(这就是所谓的munch solution)。这种做法是以编译器时间来交换移植性。

接下来是提供一个平台特定解决之道:直接验证并穿越COFF-based程序的可执行文件(此即所谓的 patch solution),不再需要nmcompilerelinkCOFF Common Object File Format的缩写,是System V pre-Release 4 UNIX系统所发展出来的格式。这两种解决方案都属于程序层面,也就是说,针对每一个需要静态初始化的.c文件,cfront 会产生出一个sti函数,执行必要的初始化操作。不论是patch solution还是munch solution,都会去寻找以sti开头的函数,并且安排它们以一种未被定义的顺序执行(由安插在main()之后第一行的一个library function _main()执行之)(译注:本书第6章对此有详细说明)。

System V COFF-specific C++编译器与cfront的各个版本平行发展。由于瞄准了一个特定平台和特定操作系统,此编译器因而能够影响链接器特地为它修改:产生出一个新的.ini section,用以收集需要静态初始化的objects。链接器的这种扩充方式,提供了所谓的environment-based solution,那当然更在program-based solution层次之上。

至此,任何以cfront program-based solution为基础的一般化(泛型)操作将令人迷惑。为什么?因为C++已经成为主流语言,它已经接收了越来越多的environment-based solutions。本书如何维护其间的平衡呢?我的策略如下:如果在不同的C++编译器上有重大的实现技术差异,我就至少讨论两种做法。但如果 cfront之后的编译器实现模型只是解决cfront原本就已理解的问题,例如对虚拟继承的支持,那么我就阐述历史的演化。当我说到传统模型时,我的意思是Stroustrup的原始构想(反映在cfront身上),它提供一种实现模范,在今天所有的商业化实现品上仍然可见。

本书组织

1章,关于对象(Object Lessons),提供以对象为基础的观念背景,以及由C++提供的面向对象程序设计范式(paradigm。译注:关于paradigm这个字,请参阅本书第1章第22页的译注)。本章包括对对象模型的一个概述,说明目前普及的工业产品,但没有对于多重继承和虚拟继承有太靠近的观察(那是第3章和第4章的重头戏)。

2章,构造函数语意学(The Semantics of Constructors),详细讨论constructor 如何工作。本章谈到constructors何时被编译器合成,以及给你的程序效率带来什么样的意义。

3章至第5章是本书的重要内容。在这里,我详细地讨论了C++对象模型的细节。第3章,Data语意学(The Semantics of Data),讨论data members的处理。第4章,Function语意学(The Semantics of Function),专注于各式各样的member functions,并特别详细地讨论如何支持virtual functions。第5章,构造、析构、拷贝语意学(Semantics of Construction, Destruction, and Copy),讨论如何支持class模型,也讨论到object的生命期。每一章都有测试程序以及测试数据。我们对效率的预测,将拿来和实际结果做比较。

6章,执行期语意学(Runtime Semantics),查看执行期的某些对象模型行为。包括临时性对象的生命及其死亡,以及对new运算符和delete运算符的支持。

7章,在对象模型的尖端(On the Cusp of the Object Model),专注于exception handlingtemplate supportruntime type identification

预定的读者

本书可以扮演家庭教师的角色,不过它定位在中级以上的C++程序员,而非C++新手。我尝试提供足够的内容,使它能够被任何有点C++基础(例如读过我的C++ Primer并有一些实际编程经验)的人接受。理想的读者是,曾经有过数年的C++编程经验,希望进一步了解底层做些什么事的人。书中某些部分甚至对于C++高手也具有吸引力,如临时性对象的产生,以及named return valueNRV)最佳化的细节等等。在与本书素材相同的各个公开演讲场合中,我已经证实了这些材料的吸引力。

程序范例及其执行

本书的程序范例主要有两个目的:

1.    为了提供书中所述C++对象模型各种概念的具体说明。

2.    提供测试,以测量各种语言性质的相对成本。

无论哪一种意图,都只是为了展现对象模型。举例而言,虽然我在书中有大量的举例,但我并非建议一个真实的3D graphic library必须以虚拟继承的方式来表现一个3D点(不过,你可以在[POKOR94]中发现作者Pokorny的确是这么做的)。

 

书中所有测试程序都在一部SGI Indigo2xL上编译执行,使用SGI 5.2 UNIX操作系统中的CCNCC编译器。CCcfront 3.0.1版(它会产生出C代码,再由一个C编译器重新编译为可执行文件)。NCCEdison Design GroupC++ front-end 2.19版,内含一个由SGI供应的程序代码产生器。至于时间测量,是采用UNIXtimex命令针对1 000万次迭代测试所得的平均值。

虽然在xL机器上使用这两个编译器,对读者而言可能觉得有些神秘,我却觉得对此书的目的而言,很好。不论是cfront或现在的Edison Design Group's C++ front-endBjarne称其为“cfront的儿子),都与平台无关。它们是一种一般化的编译器,被授权给34家以上的计算机制造商(其中包括GraySGIIntel)和软件开发环境厂商(包括CenterlineNovell,后者是原先的UNIX软件实验室)。效率的测量并非为了对目前市面上的各家编译系统做评比,而只是为了提供C++对象模型之各种特性的一个相对成本测量。至于商业评比的效率数据,你可以在几乎任何一本计算机杂志的计算机产品检验报告中获得。

致谢

参考书目

注意:许多C++ Report文章已被C++ Gems收录,并由Stanley Lippman编辑完成,参见SIGS BooksNew YorkNY1996)。

[BALL92] Ball, Michael, "Inside Templates", C++ Report (September 1992)

[BALL93a] Ball, Michael, "What Are These Things Called Templates", C++ Report (February 1993)

[BALL93b] Ball, Michael, "Implementing Class Templates", C++ Report (September 1993)

[BOOCH93] Booch, Grady and Michael Vilot, "Simplifying the Booch Components", C++ Report (June 1993)

[BORL91] Borland Language Open Architecture Handbook, Borland International Inc., Scotts Valley, CA

[BOX95] Box, Don, "Building C++ Components Using OLE2", C++ Report (March/April 1995)

[BUDD91] Budd, Timothy, An Introduction to Object-Oriented Programming, Addison-Wesley Publishing Company, Reading, MA(1991)

[BUDGE92] Budge, Kent G., James S. Peery, and Allen C. Robinson, "High Performance Scientific Computing Using C++", Usenix C++ Conference Proceedings, Portland, OR(1992)

[BUDGE94] Budge, Kent G., James S. Peery, Allen C. Robinson, and Michael K. Wong, "Management of Class Temporaries in C++ Translation Systems", The Journal of C Language Translation (December 1994)

[CARGILL95] Cargill, Tom, "STL Caveats, " C++Report (July/August 1993)

[CARROLL93] Carroll, Martin, "Design of the USL Standard Components", C++ Report (June 1993)

[CARROLL95] Carroll, Martin, and Margaret A. Ellis, "Designing and Coding Reusable C++, Addison-Wesley Publishing Company, Reading, MA(1995)

[CHASE94] Chase, David, "Implementation of Exception Handling, Part 1", The Journal of C Language Translation (June 1994)

[CLAM93a] Clamage, Stephen D., "Implementing New & Delete", C++ Report (May 1993)

[CLAM93b] Clamage, Stephen D., "Beginnings & Endings", C++ Report (September 1993)

[ELLIS90] Ellis, Margaret A. and Bjarne Stroustrup, The Annotated C++ Reference Manual, Addison-Wesley Publishing Company, Reading, MA(1990)

[GOLD94] Goldstein, Theodore C. and Alan D. Sloane, "The Object Binary Interface - C++ Objects for Evolvable Shared Class Libraries", Usenix C++ Conference Proceedings, Cambridge, MA(1994)

[HAM95] Hamilton, Jennifer, Robert Klarer, Mark Mendell, and Brian Thomson, "Using SOM with C++", C++ Report (July/August 1995)

[HORST95] Horstmann, Cay S., "C++ Compiler Shootout", C++ Report (July/August 1995)

[KOENIG90a] Koenig, Andrew and Stanley Lippman, "Optimizing Virtual Tables in C++ Release 2.0", C++ Report (March 1990)

[KOENIG90b] Koenig, Andrew and Bjarne Stroustrup, "Exception Handling for C++ (Revised)", Usenix C++ Conference Proceedings (April 1990)

[KOENIG93] Koenig, Andrew, "Combining C and C++", C++ Report (July/August 1993)

[ISO-C++95] C++ International Standard, Draft (April 28, 1995)

[LAJOIE94a] Lajoie, Josee, "Exception Handling: Supporting the Runtime Mechanism", C++ Report (March/April 1994)

[LAJOIE94b] Lajoie, Josee, "Exception Handling: Behind the Scenes", C++ Report (June 1994)

[LENKOV92] Lenkov, Dmitry, Don Cameron, Paul Faust, and Michey Mehta, "A Portable Implementation of C++ Exception Handling", Usenix C++ Conference Proceeding, Portland, OR(1992)

[LEA93] Lea, Doug, "The GNU C++ Library", C++ Report (June 1993)

[LIPP88] Lippman, Stanley and Bjarne Stroustrup, "Pointers to Class Members in C++", Implementor's Workshop, Usenix C++ Conference Proceedings (October 1988)

[LIPP91a] Lippman, Stanley, "Touring Cfront", C++ Journal, Vol.1, No.3 (1991)

[LIPP91b] Lippman, Stanley, "Touring Cfront: From Minutiae to Migraine", C++ Journal, Vol.1, No.4 (1991)

[LIPP91c] Lippman, Stanley, C++ Primer, Addison-Wesley Publishing Company, Reading, MA(1991)

[LIPP94a] Lippman, Stanley, "Default Constructor Synthesis", C++ Report (January 1994)

[LIPP94b] Lippman, Stanley, "Applying The Copy Constructor, Part1: Synthesis", C++ Report (February 1994)

[LIPP94c] Lippman, Stanley, "Applying The Copy Constructor, Part2", C++ Report (March/April 1994)

[LIPP94d] Lippman, Stanley, "Objects and Datum", C++ Report (June 1994)

[METAW94] MetaWare High C/C++ Language Reference Manual, Metaware Inc., Santa Crus, CA(1994)

[MACRO92] Jones, David and Martin J. O'Riordan, The Microsoft Object Mapping, Microsoft Corporation, 1992

[MOWBRAY95] Mowbray, Thomas J. and Ron Zahavi, The Essential Corba, John Wiley & Sons, Inc. (1995)

[NACK94] Nackman, Lee R., and John J. Barton Scientific and Engineering C++, An Introduction with Advanced Techniques and Examples, Addison-Wesley Publishing Company, Reading, MA(1994)

[PALAY92] Palay, Andrew J., "C++ in a Changing Environment", Usenix C++ Conference Proceedings, Portland, OR(1992)

[POKOR94] Pokorny, Cornel, Computer Graphics, Franklin, Beedle & Associates, Inc. (1994)

[PUGH90] Pugh, William and Grant Weddell, "Two-directional Record Layout for Multiple Inheritance", ACM SIGPLAN '90 Conference, White Plains, New York(1990)

[SCHMIDT94a] Schmidt, Douglas C., "A Domain Analysis of Network Daemon Design Dimensions", C++ Report (March/April 1994)

[SCHMIDT94b] Schmidt, Douglas C., "A Case Study of C++ Design Evolution", C++ Report (July/August 1994)

[SCHWARZ89] Schwarz, Jerry, "Initializing Static Variables in C++ Libraries", C++ Report (February 1989)

[STROUP82] Stroustrup, Bjarne, "Adding Classes to C: An Exercise in Language Evolution", Software: Practices & Experience, Vol.13 (1983)

[STROUP94] Stroustrup, Bjarne, "The Design and Evolution of C++", Addison-Wesley Publishing Company, Reading, MA(1994)

[SUN94a] The C++ Application Binary Interface, SunPro, Sun Microsystems, Inc.

[SUN94b] The C++ Application Binary Interface Rationale, SunPro, Sun Microsystems, Inc.

[VELD95] Veldhuizen, Todd, "Using C++ Template Metaprograms", C++ Report (May 1995)

[VINOS93] Vinoski, Steve, "Distributed Object Computing with CORBA", C++ Report (July/August 1993)

[VINOS94] Vinoski, Steve, "Mapping CORBA IDL into C++", C++ Report (September 1994)

[YOUNG95] Young, Douglas, Object-Oriented Programming with C++ and OSF/Motif, 2d ed., Prentice-Hall(1995)

 

0 

读(译者的话)

读者对象

很不容易三言两语就说明此书的适当读者。作者Lippman参与设计了全世界第一套C++编译器cfront,本书就是一位伟大的C++编译器设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码)和implicit(隐藏于程序代码背后)的C++语意。

对于C++程序老手,这必然是一本让你大呼过瘾的绝妙好书。

C++老手分两类:一种人把语言用得烂熟,OO观念也有;另一种人不但如此,还对于台面下的机制,如编译器合成的default constructorobject的内存布局等有莫大的兴趣。本书对于第二类老手的吸引力自不待言;至于第一类老手,或许你没那么大的刨根究底的兴趣,不过我还是非常推荐你阅读此书。了解C++对象模型,绝对有助于你在语言本身以及面向对象观念两方面的层次提升。

你需要细细推敲每一个句子、每一个例子,囫囵吞枣是完全没有用的。作者是C++大师级人物,并且参与开发了第一套C++编译器,他的解说以及诠释鞭辟入里,你务必在看过每一小段之后,融会贯通,把思想观念化为己有,再接续另一小节。但阅读顺序并不需要按照书中的章节排列。

阅读顺序

我个人认为,第134章最能带给读者迅速而最大的帮助,这些都是经常引起程序员困惑的主题。作者在这些章节中有不少示意图(我自己也加了不少)。你或许可以从这三章挑着看起。

其他章节比较晦涩一些(我的感觉),不妨视可而择之

当然,这都是十分主观的认定。客观的意见只有一个:你可以随你的兴趣与需求,从任一章开始看起。各章之间没有必然关联性。

翻译风格

太多朋友告诉我,他们阅读中文计算机书籍,不论是著作或译作,最大的阅读困难在于一大堆没有标准译名的技术名词或习惯用语(至于那些误谬不知所云的奇怪作品当然本就不在考虑之列)。其实,就算国家相关机构指定了统一译名(或曾有过,谁知道?),流通于工业界与学术界之间的还是原文名词与术语。

对于工程师,我希望我所写的书和我所译的书能够让各位读来通体顺畅;对于学生,我还希望多发挥一点引导的力量,引导各位多使用、多认识原文术语和专有名词,不要说出像无模式对话盒(modeless dialog这种奇怪的话。

由于本书读者定位之故,我决定保留大量的原文技术名词与术语。我清楚地知道,在我们的技术领域里,研究人员或工程师如何使用这些语汇。

 

当然,有些中文译名应用较普遍,也较贴切,我并不排除使用。其间的挑选与决定,不可避免地带了点个人色彩。

下面是本书出现的原文名词(按字母排序)及其意义:

英文名词       中文名词或(及)其意义

access level     访问级,存取级。就是C++publicprivateprotected三种等级

access section  访问区段,存取区段。就是class中的publicprivateprotected三种段落

alignment       边界调整,调整至某些bytes的倍数。其结果视不同的机器而定。例如32位机器通常调整至4的倍数

bind 绑定,将程序中的某个符号真正附着(决议)至一块实例上

chain       串链

class

class hierarchy       class体系,class层次结构

composition    组合。通常与继承(inheritance)一同讨论

concrete inheritance       具体继承(相对于抽象继承)

constructor     构造函数

data member   数据成员(或被称为member variable

declarationdeclare      声明

definitiondefine  定义(通常附带在内存中挖一块空间的行为)

derived    派生

destructor       析构函数

encapsulation  封装

explicit    显式的(通常指C++程序代码中明确出现的)

hierarchy 体系,层次结构

implement      实现(动词)

implementation      实现品、实现物。本书有时候指C++编译器。大部分时候是指class member function的内容

implicit   隐式的、暗喻的(通常指未出现在C++程序代码中的)

inheritance      继承

inline      内联(C++的一个关键词)

instance   实例(有些书籍译为案例,极不妥当)

layout     布局。本书常常出现这个字,意指object在内存中的数据分布情况

mangle    名称切割重组(C++对于函数名称的一种处理方式)

member function    成员函数。或被称为function member

members 成员,泛指data membersmember functions

object      对象(根据class的声明而完成的一份占有内存的实例)

offset      偏移位置

operand   操作数

operator  运算符

overhead 额外负担(因某种设计,而导致的额外成本)

overload  重载

overloaded function       多载函数

override  改写(对virtual function的重新设计)

paradigm 范式(请参考第1章第22页)

pointer    指针

polymorphism 多态(面向对象最重要的一个性质)

programming  程序设计、程序化

reference 参考、引用(动词)

reference C++&运算符所代表的东西。当做名词解

resolve    决议。函数调用时链接器所进行的一种操作,将符号与函数实例产生关联。如果你调用func()而链接时找不到func()实例,就会出现“unresolved externals”链接错误

slot  表格中的一格(一个元素),条孔,条目,条格

subtype   子类型

type 类型,类别(指的是intfloat等内建类型,或C++ classes等自定类型)

virtual     虚拟

virtual function      虚拟函数

virtual inheritance  虚拟继承

virtual table    虚拟表格(为实现虚拟机制而设计的一种表格,内放virtual functions的地址)

 

有时候考虑到上下文的因素,面对同一个名词,在译与不译之间,我可能会有不同的选择。例如,面对“pointer”,我会译为指针,但由于我并未将reference译为参考(实在不对味),所以如果原文是“the manipulation of a pointer or reference in C++……”,为了中英对等或平衡的缘故,我不会把它译为“C++中对于指针和reference的操作行为……”,我会译为“C++中对于pointerreference的操作行为……”

译注

书中有一些译注。大部分译注,如果比较短的话,会被我直接放在括号之中,接续本文。较长的译注,则被我安排在被注文字的段落下面(紧临,并加标示)。

原书错误

这本书虽说质地极佳,但制作的严谨度却不及格!有损Lippman的大师地位。

属于作者笔误之类的错误,比较无伤大雅,例如少了一个;符号,或是多了一个;符号,或是少了一个}符号,或是多了一个)符号,等等。比较严重的错误,是程序代码变量名称或函数名称或class名称与文字叙述不一致,甚或是图片中对于object布局的画法,与程序代码中的声明不一致。这两种错误都会严重耗费读者的心神。

只要是被我发现的错误,都已被我修正。以下是错误更正列表。

    示例:L5表示第5行,L-9表示倒数第9行。页码所示为原书页码。

页码       原文位置       原文内容       应修改为

p.35 最后一行       Bashful(),       Bashful();

p.57 表格第二行    1.32.36   1:32.36

p.61 L1   memcpy...程序代码最后少了一个)  

p.61 L10  Shape()...程序代码最后少了一个}    

p.64 L-9  程序代码最后多了一个 ;   

p.78 最后四行码    ==   似乎应为 =

p.84 3.1b说明   struct Point3d class Point3d

p.87 L-2  virtual...程序代码最后少了一个;    

p.87 全页多处       pc2_2(不符合命名意义)  pc1_2(符合命名意义)

p.90 3.2a说明   Vptr placement and end of class    Vptr placement at end of class

p.91 3.2b    __vptr__has_vrts    __vptr__has_virts

p.92 L-7     class Vertex2d class Vertex3d

p.92 L-6     public Point2d       public Point3d

p.93 3.4说明     Vertex2d的对象布局    Vertex3d的对象布局

p.92~p.94              符号名称混乱,前后误谬不符    已全部更改过

p.97 L2      public Point3d, public Vertex 配合图3.5a和图3.5b,应调整顺序为public Vertex, public Point3d

p.99 3.5a    符号与书中程序代码多处不符    已全部更改过

p.100      3.5b    符号与书中程序代码多处不符    已全部更改过

p.100      L-2  ? pv3d + ...最后多了一个)  

p.106      L16  pt1d::y    pt2d::_y

p.107      L10  & 3d_point::z;       &Point3d::z;

p.108      L6   & 3d_point::z;       &Point3d::z;

p.108      L-6  int d::*dmp, d *pd  int Derived::*dmp, Derived *pd

p.109      L1   d *pd      Derived *pd

p.109      L4   int b2::*bmp = &b2::val2;     int Base2::*bmp = &Base2::val2;

p.110      L2   不符合稍早出现的程序代码       pt3d改为Point3d

p.115      L1   magnitude()    magnitude3d()

p.126      L12  Point2d pt2d = new Point2d; ptr = new Point2d;

p.136      4.2右下     Derived::~close()   Derived::close()

p.138      L-12       class Point3d...最后少了一个{    

p.140      程序代码       没有与文字中的class命名一致   所有的pt3d改为Point3d

p.142      L-7  if ( this ...程序代码最右边少了一个) 

p.143      程序代码       没有与文字中的class命名一致   所有的pt3d改为Point3d

p.145      L-6  pointer::z()     Point::z()

p.147      L1   pointer::*pmf  Point::*pmf

p.147      L5   point::x() Point::x()

p.147      L6   point::z() Point::z()

p.147      中段码L-1     程序代码最后缺少一个)   

p.148      中段码L1      ptr->*pmf)函数最后少了一个;  

p.148      中段码L-1     *ptr->vptr[..函数最后少了一个)  

p.150      程序代码       没有与文字中的class命名一致   所有的pt3d改为Point3d

p.150      L-7  pA.__vptr__pt3d...最后少了一个;   

p.152      L4   point new_pt;  Point new_pt;

p.156      L7   {     }

p.160      L11, L12 Abstract_Base Abstract_base

p.162      L-3  Abstract_base函数最后少了一个;   

p.166      中,码L3      Point1 local1 = ...  Point local1 = ...

p.166      中,码 L4     Point2 local2; Point local2;

p.174      中,码L-1     Line::Line()函数最后多了一个;

p.174      中下,码L-1 Line::Line()函数最后多了一个;

p.175      中上,码L-1 Line::~Line()函数最后多了一个;     

p.182      中下,码L6   Point3d::Point3d()  PVertex::PVertex()

p.183      上,码L9      Point3d::Point3d()  PVertex::PVertex()

p.185      上,码L3      y = 0.0之前缺少float  

p.186      中下,码L6   缺少一个return    

p.187      中,码L3      const Point3d &p   const Point3d &p3d

p.204      下,码L3      缺少一个return 1;

p.208      中下,码L2   new Pvertex;   new PVertex;

p.219      上,码L1      __nw(5*sizeof(int));      __new(5*sizeof(int));

p.222      上,码L8      // new ( ptr_array...程序代码少了一个;   

p.224      中,码L1      Point2w ptw = ...   Point2w *ptw = ...

p.224      下,码L5      operator new()函数定义多了一个;   

p.225      上,码L2      Point2w ptw = ...   Point2w *ptw = ...

p.226      下,码L1      Point2w p2w = ...  Point2w *p2w = ...

p.229      中,码L1      c.operator==( a + b );    c.operator=( a + b );

p.232      中下,码L2   x xx;       X xx;

p.232      中下,码L3   x yy;       X yy;

p.232      下,码L2      struct x _1xx;  struct X _1xx;

p.232      下,码L3      struct x _1yy;  struct X _1yy;

p.233      L2      struct x __0__Q1;   struct X __0__Q1;

p.233      L3      struct x __0__Q2;   struct X __0__Q2;

p.233      中,码    if条件句的最后多了一个;

p.253      L-1     foo()函数最后多了一个;  

 

 

推荐

我个人翻译过不少书籍,每一本都精挑细选后才动手。(品质不够的原文书,译它做啥?!)在这些译本当中,我从来不做直接而露骨的推荐。好的书籍自然而然会得到识者的欣赏。过去我译的那些明显具有实用价值的书籍,总有相当数量的读者有强烈的需求,所以我从不担心没有足够的人来为好书散播口碑。但Lippman的这本书不一样,它可能不会为你带来明显而立即的实用性,它可能因此在书店中蒙上一层灰(其原文书我就没听说多少人读过),枉费我从众多原文书中挑出这本好书。我担心听到这样的话:

对象模型?呵,我会写C++程序,写得一级棒,这些属于编译器层面的东西,于我何有哉!

对象模型是深层结构的知识,关系到与语言无关、与平台无关、跨网络可执行软件组件(software component)的基础原理。也因此,了解C++对象模型,是学习目前软件组件三大规格(COMCORBASOM)的技术基础。

如果你对软件组件(software component)没有兴趣,C++对象模型也能够使你对虚拟函数、虚拟继承、虚拟接口有脱胎换骨的新认知,或是对于各种C++写法所带来的效率利益有通盘的认识。

我因此要大声地说:有经验的C++ programmer都应该看看这本书。

如果你对COM有兴趣,我也要同时推荐你看另一本书:Essential COMDon Box著,Addison Wesley公司1998年出版(《COM本质论》,侯捷译,碁峰1998)。这也是一本论述非常清楚的书籍,把COM的由来(为什么需要COM、如何使用COM)以循序渐进的方式阐述得非常深刻,是我所看过的最理想的一本COM基础书籍。

Essential COM之前,你最好有这本Inside The C++ Object Model的基础。

阅读(1160) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~