天天看点

inside the c++ object model 读书笔记(第一章)

Chapter 1     Object Lessons C语言是面向过程的编程方法,由一堆基于算法而分割的任务来实现。而C++增加了数据和操作的封装,是面向对象的编程方法 Layout Costs for Adding Encapsulation 基本上不会有什么cost的增加。但是如果你使用了virtual,会有一些空间和时间消耗。如果用了多继承,在子类和父类的转换时会有一些overhead。一般来说,c++程序相对于c程序并不会大多少或者慢多少。 C++ 对象模型 在C++中,有两种类的成员数据类型—static和非static.三种成员函数—static、非static和virtual. Ø A Simple Object Model 一个简单的对象模型就是对于类中的所有成员—包括数据成员和函数,并不是直接放在对象中,而是用一个一个指针一一对应的指向它们。这样子一个对象由一组指针序列组成。类的大小就是 (指针大小*成员数目).这样的好处是避免了不同数据类型大小不一造成的空间申请问题。 Ø A Table-driven Object Model 由表驱动的对象模型将数据和操作分开。一个对象中包含两个指针,一个指向数据成员表,另一个指向函数成员表。 Ø The C++ Object Model Stroustrup初始的C++ 对象模型来自于对简单对象模型在空间和访问时间上的优化。非static数据直接在类对象中存储;Static数据保存在类对象之外。Static和非static函数成员保存在类对象之外。 Virtual虚函数通过两个步骤来支持: 1.       每个类生成一张包含指向虚函数的指针(s)的表,一般叫做虚函数表(vtable)。 2.       一个指向虚函数表的指针(vptr),将被插入到每个实际的类对象中。关于Vptr的操作由编译器根据具体情况(后面章节会详细讲)自动完成。用于支持RTTI的type_info对象也放在vtable中,一般会放在第一个位置。 Adding inheritance C++支持单继承也支持多继承。另外,还支持虚继承(virtual inheritance)。在虚继承中,只有一个基类的实例会被保存,而不管这个类在继承链中被继承了多少次。 How the Object Model Effects Program 会隐藏很多东西在背后。所以才要看这本书。咔咔  A Keyword Distinction 讨论c和c++一些关键字的问题。主要是struct和class关键字的区别及原因。   An Object Distinction C++支持三种编程范例(paradigm) 1.       Procedural Model 2.       ADT(abstract data type) Model 3.       Object-oriented Model C++中支持多态的三种方法: 1.       通过一系列的隐形转换。比如由子类的指针转成基类指针: Shape *ps = new Circle(); 2.       通过虚函数机制 3.       通过dynamic_cast和typeid操作符 一个类对象在内存的大小由一下因素决定: Ø  非static数据成员的大小累加 Ø 对齐(alignment)机制所需要添加的空间 Ø 支持virtuals增加的空间 The Type of a Pointer 一个指针本身的大小是确定的,而不管它是指向什么类型,一般就是机器指令地址的大小。指针类型的不同主要是在于其所指的对象的不同。指针的类型告诉编译器如何解析其包含的地址的内容和要解析的内容的大小。 而对于void*型指针,它可以指向任何类型,其实就是包含一个地址值而已;但是你不能通过void*指针对对象进行操作。 所以通常情况下的cast并不会对实际包含的地址做改变(多重继承可能造成改变)。它只是改变了该地址对应内存要解析的大小和构成。 Adding Polymorphism 这部分要画图才讲的清楚。基本上实现多态就是在基类里插入一个vptr(如果有多继承,情况会更复杂,后面章节会讲)。这个vptr可以插入在最前面,也可以插入在末尾,其实也可以放在中间。标准里并没有规定vptr的位置。而VC是将其放在最前。 由于插入了vptr,包含虚函数的类对象大小会增加。一般是4bytes. 由于vptr是放在基类中,所以我们可以用一个基类的指针来调用子类的虚函数。因为对于具体对象的虚函数表中的函数来说,还是依具体对象的类型而定的。 而对于一个基类的对象来说,它的大小并不会改变。如果你用一个继承类来初始化或者复制给基类。继承类会被切割来适应基类的大小。而由于virtual的机制是根据实际的对象类型来决定的。这种情况下,该对象vptr指向的仍是基类的vtable.

继续阅读