描述
开 本: 16开纸 张: 轻型纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787121149528丛书名: 传世经典书丛
作者Lippman参与设计了全世界*套C 编译程序cfront,这本书就是一位伟大的C 编译程序设计者向你阐述他如何处理各种explicit(明确出现于C 程序代码中)和implicit(隐藏于程序代码背后)的C 语意。 本书专注于C 面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得多么大的效率。Lippman澄清了那些关于C 额外负荷与复杂度的各种错误信息和迷思,但也指出其中某些成本和利益交换确实存在。他阐述了各式各样的实现模型,指出它们的进化之道及其本质因素。书中涵盖了C 对象模型的语意暗示,并指出这个模型是如何影响你的程序的。 。
目 录
本立道生(侯捷 译序) 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
策略性正确的struct(The 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 new和delete运算符 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 Identification,RTTI) 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
本立道生 (侯捷 译序)
对于传统的结构化(sequential)语言,我们向来没有太多的疑惑,虽然在函数调用的背后,也有着堆栈建制、参数排列、返回地址、堆栈清除等等幕后机制,但函数调用是那么的自然而明显,好像只是夹带着一个包裹,从程序的某一个地点跳到另一个地点去执行。
但是对于面向对象(Object Oriented)语言,我们的疑惑就多了。究其因,这种语言的编译器为我们(程序员)做了太多的服务:构造函数、析构函数、虚拟函数、继承、多态……有时候它为我们合成出一些额外的函数(或运算符),有时候它又扩张我们所写的函数内容,放进更多的操作。有时候它还会为我们的objects加油添醋,放进一些奇妙的东西,使你面对sizeof的结果大惊失色。
我心里头一直有个疑惑:计算机程序基础的形式,总是脱离不了一行一行的循序执行模式,为什么OO(面向对象)语言却能够“自动完成”这么多事情呢?另一个疑惑是,威力强大的polymorphism(多态),其底层机制究竟如何?
如果不了解编译器对我们所写的C 代码做了什么手脚,这些困惑永远解不开。
这本书解决了过去令我百思不解的诸多疑惑。我要向所有已具备C 多年程序设计经验的同好们大力推荐这本书。
这本书同时也是跃向组件软件(component-ware)基本精神的“跳板”。不管你想学习COM(Component Object Model)、CORBA(Common Object Request Broker Architecture)或是SOM(System Object Model),了解C Object Model,将使你更清楚软件组件(components)设计上的难点与运用之道。不但我自己在学习COM的道路上有此强烈的感受,Essential COM(《COM本质论》,侯捷译,碁峰1998)的作者Don Box也在他的书中推崇Lippman的这一本卓越的书籍。
是的,这当然不会是一本轻松的书籍。某些章节(例如3、4两章)可能给你立即的享受——享受于面对底层机制有所体会与掌控的快乐;某些章节(例如5、6、7三章)可能带给你短暂的痛苦——痛苦于艰难深涩、难以吞咽的内容。这些快乐与痛苦,其实就是我翻译此书时的心情写照。无论如何,我希望通过我的译笔,把这本难得的好书带到更多人面前,引领大家见识C 底层建设的技术之美。
侯捷 2011.10.20 于新竹
[email protected]
请注意:本书特点,作者Lippman在其前言中有很详细的描述,我不再多言。翻译用词与心得,记录在第0章(译者的话)之中,对您或有导读之功。
请注意:原文本有大大小小约80~90个笔误。有的无伤大雅,有的影响阅读顺畅甚巨(如前后文所用符号不一致、内文与图形所用符号不一致——甚至因而导致图片的文字解释不正确)。我已在第0章(译者的话)列出所有我找到的错误。此外,某些场合我还会在错误出现之处再加注,表示原文内容为何。这么做不是画蛇添足,也不为彰显什么。我知道有些读者拿着原文书和中译书对照着看,我把原书错误加注出来,可免读者怀疑是否我打错字或是译错了。另一方面也是为了文责自负……唔……万一Lippman是对的而J.J.Hou错了呢?!我虽有相当把握,但还是希望明白摊开来让读者检验。
前 言 (Stanley B. Lippman)
差不多有10年之久,我在贝尔实验室(Bell Laboratories)埋首于C 的实现任务。初的工作是在cfront上面(Bjarne Stroustrup的个C 编译器),从1986年的1.1版到1991年9月的3.0版。然后移转到Simplifier(这是我们内部的命名),也就是Foundation项目中的C 对象模型部分。在Simplifier设计期间,我开始酝酿本书。
Foundation项目是什么?在 Bjarne 的领导下,贝尔实验室中的一个小组探索着以C 完成大规模程序设计时的种种问题的解决之道。Foundation项目是我们为了构建大系统而努力定义的一个新的开发模型(我们只使用C ,并不提供多重语言的解决方案)。这是个令人兴奋的工作,一方面是因为工作本身,一方面是因为工作伙伴:Bjarne、Andy Koenig、Rob Murray、Martin Carroll、Judy Ward、Steve Buroff、Peter Juhl,以及我自己。Barbara Moo管理我们这一群人(Bjarne和Andy除外)。Barbara Moo常说管理一个软件团队,就像放牧一群骄傲的猫。
我们把Foundation想象成一个核心,在那上面,其他人可以为使用者铺设一层真正的开发环境,把它整修为他们所期望的UNIX或Smalltalk模型。私底下我们把它称为Grail(传说中耶稣后晚餐所用的圣杯),人人都想要,但是从来没人找到过!
Grail使用一个由Rob Murray发展出来并命名为ALF的面向对象层次结构,提供一个永久的、以语意为基础的表现法。在Grail中,传统编译器被分解为数个各自分离的可执行文件。parser负责建立程序的ALF表现法。其他每一个组件(如type checking、simplification、code generation)以及工具(如browser)都在程序的一个ALF表现体上操作(并可能加以扩展)。Simplifier是编译器的一部分,处于type checking和code generation之间。Simplifier 这个名称是由Bjarne所倡议的,它原本是cfront的一个阶段(phase)。
在type checking和code generation之间,Simplifier做什么事呢?它用来转换内部的程序表现。有三种转换风味是任何对象模型都需要的:
1.与编译器息息相关的转换(Implementation-dependent transformations)
这是与特定编译器有关的转换。在ALF之下,这意味着我们所谓的“tentative”nodes。例如,当parser看到这个表达式:
fct();
它并不知道是否(a)这是一个函数调用操作,或者(b)这是overloaded call operator在class 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 functions、virtual base class和inheritance的一般支持、new和delete运算符、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 对象模型的底层机制并未标准化,那么你可
评论
还没有评论。