《深度探索C++对象模型》读书笔记——第一章

来源:互联网 发布:网络禁书txt下载 编辑:程序博客网 时间:2024/05/22 03:10

《深度探索C++对象模型》
读书笔记
前言:知其然,亦知其所以然
1、 本书为中高级C++程序员所写;
2、 本书专注于:各种C++对象模型支持的底层实现机制;
3、 程序员应了解底层实现模型,才能成为高手。
Lippman:
1. 任何对象模型都需要的三种转换风味:
(1) 与编译器息息相关的转换
(2) 语言语义转换
(3) 程序代码和对象模型的转换
2. C++对象模型的两种解释
(1) 语言中直接支持面向对象程序设计的部分
(2) 对于各种支持的底层实现机制
3. C++ class的完整virtual functions在编译时期就固定下来了,程序员没有办法在执行期动态增加或取代其中某一个。这使得虚拟函数调用操作得以有快速的派送结果,付出的却是执行期的弹性。
4. 目前所有编译器对于virtual function的实现都是使用各个class专属的virtual table,大小固定,并且在程序执行前就构造好了。
5. C++对象模型的底层机制并未标准化,它会因实现品(编译器)和时间的变动而不同。
第一章 关于对象
本章难点:
1、表格驱动对象模型
2、virtual产生的额外负担
知识点:
1.0导言
C++在布局以及存取时间上的主要额外负担是由virtual引起的,包括:
(1) virtual function
(2) virtual base class(虚拟继承)
还有一些发生在“一个derived class和其第二或后继之base class的转换”上的多重继承。
1.1 C++对象模型
1、在C++对象模型中,
(1)nonstatic data members被配置于每一个class object之内,
(2)static data members则被存放在所有的class object之外,
static和nonstatic function members也被放在所有的class object之外,
(3) virtual functions则以两个步骤支持:
1) 每个class产生一堆指向virtual functions的指针,放在virtual table (vtbl)中;
2) 每个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的位置。

一、简单对象模型:
• object内存放指向成员的指针,不存放成员。
• 牺牲空间和运行时的效率。解决成员类型不一致带来的存储空间不一致问题。
这里写图片描述

二、表格驱动对象模型
表格驱动对象模型:
 需要两个表,数据成员表和成员函数表,数据成员表直接存放数据本身,成员函数表存放每个函数的地址。
 object存放这指向这两个表的指针。
 成员函数表的思想可以支持虚函数实现。
这里写图片描述
三、C++对象模型
(1) Stroustrup设计,从简单对象模型派生而来。
(2) 非静态数据成员存放在每一个class object之内,静态数据成员存放在个别的class object之外。
(3) 静态和非静态的成员函数也存放在个别的class object之外。
(4) 虚函数则通过虚函数表vtbl和指向虚函数表的指针vptr实现:
(5) 每个class object有一个vptr,指向相关的vtbl。
(6) vptr的设定由类的构造/析构/拷贝函数完成。
(7) vtbl表第一项是每个class关联的type_info object(用来支持运行时类型识别RTTI),其他的每一项存放着指向虚函数的地址。
这里写图片描述

四、多重继承

class istream: virtual public IOS{};
class ostream: virtual public IOS{}; 虚拟继承
这里写图片描述
这里写图片描述
这里写图片描述
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:
(1) 程序模型procedural model
(2) 抽象数据类型模型abstract data type model, ADT
(3) 面向对象数据模型object-oriented model,OO
2. 虽然可以直接或间接处理继承体系中的一个base class object,但只有通过pointer或reference的间接处理,才能支持OO程序设计所需的多态性质。
3. C++中,多态只存在于public class体系中,nonpublic的派生行为以及类型为void*的指针可以说是多态,但它们没有被语言明白地支持,必须由程序员通过显示的转型操作来管理。
4. C++以下列方法支持多态:
(1) 经由一组隐含的转化操作,如把一个derived class指针转化为一个指向其public base type的指针;
(2) 经由虚拟机制;
(3) 经由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;也支持具体的ADT程序风格,即object-based OB,不支持多态,不支持类型的扩充。
多态只能由指针或引用(而不能通过实例对象)来实现,根本原因在于:
 指针和引用(通常以指针来实现)的大小是固定的(一个 word),而对象的大小却是可变的。其类的指针和引用可以指向(或引用)子类,但是基类的对象永远也只能是基类,没有变化则不可能引发多态。
 一个指针或引用绝不会引发任何“与类型有关的内存委托操作”,在指针类型转换时会受到的改变的只有它们所指向内存的解释方式而已。(例如指针绝不会引发空间的slice,因为它们大小相同)

阅读全文
0 0
原创粉丝点击