面向对象编程的时候总会好奇,成员变量存放在哪里,成员函数存放在内存的哪里,static变量又存放在哪里?都是在声明的object里吗?通过阅读《深度探索C++对象模型》,该类的问题都能找到答案。
C++的设计者从简至繁是提出过几个对象模型,我在此一一介绍:
简单对象模型
第一个模型十分简单,它最大地减低了C++编译器的设计复杂度,但牺牲了空间和执行期的效率。在这个简单模型中,一个object是一系列的slots,每一个slot指向一个members。Members按其声明顺序,各被指定一个slot。每一个data member都有自己的一个slot。下图可说明此模型:
在这个简单模型下,members本身并不放在object之中。只有”指向member的指针”才放在object内。这么做可以避免”members有不同的类型,因而需要不同的存储空间”所招致的问题。Object中的members是以slot的索引值来寻址的,本例之中_x的索引是6,_point_count的索引是7。一个class object的大小很容易计算出来:”指针大小,乘以class中所声明的members个数”便是。
虽然这个模型并没有被应用于实际产品上,不过关于索引或slot个数的观念,倒是被应用到C++的”指向成员的指针”(pointer-to-member)观念之中。
表格驱动对象模型
为了对所有classes的所有objects都有一致的表达方式,另一种对象模型是把所有与members相关的信息抽出来,放在一个data member table和一个member function table之中,class object本身则内含指向这两个表格的指针。Member function table是一系列的slots,每一个slot指出一个member function;Data member table则直接持有data本身,如下图:
虽然这个模型也没有实际应用于真正的C++编译器身上,但member function table 这个观念却成为支持virtual functions的一个有效方案 。
C++ 对象模型
C++著名程序员Stroustrup当初设计(目前仍占有优势)C++对象模型是从简单对象模型派生而来的,并对内存空间和存取时间做了优化。在此模型中,Nonstatic data members 被配置于每一个class object之内,static data members则被存放在个别的class object之外。Static和nonstatic function members也被放在个别的class object之外。Virtual functions则以两个步骤支持之:
1.每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table(vtbl)。
2.每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的constructor、destructor和copy assignment运算符自动完成(我将在第5章讨论这个问题)。每一个class所关联的type_info object(用以支持runtime type identification,RTTI)也经由virtual table被指出来,通常放在表格的第一个slot。
最后这个模型不正是我们现在大多数书籍上都提到的模型吗?