Inside The C++ Object Model
Stanley B. Lippman
屋檐下的水滴--读书笔记系列
《深度探索C++对象模型》读书笔记 http://blog.csdn.net/dwater
Inside The C++ Object Model
Stanley B. Lippman
屋檐下的水滴--读书笔记系列
《深度探索C++对象模型》读书笔记 http://blog.csdn.net/dwater
前 言 Stanley B.Lippman
1. 任何对象模型都需要的三种转换风味:
ü 与编译器息息相关的转换
ü 语言语义转换
ü 程序代码和对象模型的转换
2. C++对象模型的两种解释
ü 语言中直接支持面向对象程序设计的部分
ü 对于各种支持的底层实现机制
3. C++ class的完整virtual functions在编译时期就固定下来了,程序员没有办法在执行期动态增加或取代其中某一个。这使得虚拟函数调用操作得以有快速的派送结果,付出的却是执行期的弹性。
4. 目前所有编译器对于virtual function的实现都是使用各个class专属的virtual table,大小固定,并且在程序执行前就构造好了。
5. C++对象模型的底层机制并未标准化,它会因实现品(编译器)和时间的变动而不同。
2002-6-23
关于对象 Object Lessons
1.1 C++对象模式
1. C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括virtual function机制和virtual base class 机制,还有一些发生在“一个derived class和其第二或后继之base class的转换”上的多重继承。
2. 在C++对象模型中,nonstatic data members被配置于每一个class object之内,static data members则被存放在所有的class object之外,static和nonstatic function members也被放在所有的class object之外,virtual functions则以两个步骤支持:每个class产生一堆指向virtual functions的指针,放在virtual table (vtbl)中;每个class object被添加一个指针vptr,指向相关的virtual table。每个class所关联的type_info object也经由vtbl指出,通常是放在vtbl的第一个slot处。vptr由每一个class的construtor、destructor以及copy assignment operator自动完成。以上模型的主要优点在于空间和存取时间的效率,主要缺点是,只要应用程序所用到的class object的nonstatic data members有所修改,那么应用程序代码就必须重新编译。
3. C++最初所采用的继承模型并不运用任何间接性,base class subobject的data members直接放置于derived class object中。优点是提供对base class members紧凑且高效的存取,缺点是base class members的任何改变,都将导致使用其derived class 的object的应用程序代码必须重新编译。
4. virtual base class的原始模型是在class object中为每一个有关联的virtual base class加上一个指针,其他演化出来的模型不是导入一个virtual base class table,就是扩充原已存在的vtbl,用以维护每一个virtual base class的位置。
1.2关键词所带来的差异
1. 可以说关键词struct的使用伴随着一个public接口的声明,也可以说它的用途只是为了方便C程序员迁徙至C++部落。
2. C++中凡处于同一个access section的数据,必定保证以声明次序出现在内存布局中,然而被放在多个access sections中的各笔数据排列次序就不一定了。同样,base classes和derived classes的data members的布局也没有谁先谁后的强制规定。
3. 组合composition而非继承才是把C和C++结合在一起的唯一可行方法。
1.3对象的差异
1. C++程序设计模型支持三种程序设计典范programming paradigms:
ü 程序模型procedural model
ü 抽象数据类型模型abstract data type model, ADT
ü 面向对象数据模型object-oriented model,OO
2. 虽然可以直接或间接处理继承体系中的一个base class object,但只有通过pointer或reference的间接处理,才能支持OO程序设计所需的多态性质。
3. C++中,多态只存在于public class体系中,nonpublic的派生行为以及类型为void*的指针可以说是多态,但它们没有被语言明白地支持,必须由程序员通过显示的转型操作来管理。
4. C++以下列方法支持多态:
ü 经由一组隐含的转化操作,如把一个derived class指针转化为一个指向其public base type的指针;
ü 经由虚拟机制;
ü 经由dynamic_cast和typeid运算符。
5. 多态的主要用途是经由一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。这个接口是以virtual function机制引发的,它可以在执行期根据object的真正类型解析出到底是哪一个函数实体被调用。
6. 一个class object所需的内存,一般而言由以下部分组成:
ü nonstatic data members的总和大小;
ü 任何由于alignment需求而填补上去的空间;
ü 为支持virtual而由内部产生的任何额外负担。
7. 一个pointer或reference,不管它指向哪一种数据类型,指针本身所需的内存大小是固定的。本质上,一个reference通常是以一个指针来实现,而object语法如果转换为间接手法,就需要一个指针。
8. 指向不同类型之指针的差异,既不在其指针表示法不同,也不在其内容不同,而是在其所寻址出来的object类型不同,亦即指针类型会教导编译器如何解释某个特定地址中的内存内容及大小。它们之所以支持多态,是因为它们并不引发内存中任何与类型有关的内存委托操作,会受到改变的只是它们所指向的内存的大小和内容的解释方式。
9. 转型cast操作其实是一种编译指令,大部分情况下它并不改变一个指针所含的真正地址,它只是影响被指向之内存的大小和内容的解释方式。
10.一个base class object被直接初始化或指定为一个derived object时,derived object就会被切割sliced,以塞入较小的base type内存中,多态于是不再呈现。一个严格的编译器可以在编译时期解析一个通过该object而触发的virtual function调用操作,从而回避virtual机制。这时,如果virtual function被定义为inline,则会有效率上的收获。
11.C++通过class的pointer和reference来支持多态,这种程序设计风格就是所谓的OO;C++也支持具体的ADT程序风格,如今被称为object-based OB,不支持多态,不支持类型的扩充。
2002-6-25
构造函数语意学The Semantics of Constructors
1. Jerry Schwarz,iostream函数库建构师,曾为了让cin能够求得一个真假值,于是他为它定义了一个conversion运算符operator int()。但在语句cin << intVal中,其行为出乎意料:程序原本要的是cout而不是cin!但是编译器却找到一个正确的诠释:将cin转型为整型,现在left shift operator <<就可以工作了!这就是所谓的“Schwarz Error”。Jerry最后以operator void *()取代operator int()。
2. 引入关键词explicit的目的,就是为了提供程序员一种方法,使他们能够制止单一参数的constructor被当作一个conversion运算符。其引入是明智的,但其测试应该是残酷的!
2.1 Default Constructor的建构操作
1. global objects的内存保证会在程序激活的时候被清为0。local objects配置于程序的堆栈中,heap objects配置于自由空间中,都不一定会被清为0,它们的内容将是内存上次被使用后的遗迹。
2. 在各个不同的版本模块中,编译器避免合成出多个default constructor的方法:把合成的default constructor、copy constructor