C++在加入封装后(只含有数据成员和普通成员函数)的布局成本增加了多少?
答案是并没有增加布局成本。就像C struct一样,memeber functions虽然含在class的声明之内,却不出现在object中。每一个non-inline member function只会诞生一个函数实体。至于每一个“拥有零个或一个定义的” inline function则会在其每一个使用者(模块)身上产生一个函数实体。
C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括:
- virtual funciton机制,用以支持一个有效率的“执行期绑定”(runtime binding)
- virtual base class,用以实现“多次出现在继承体系中的base class,有一个单一而被共享的实体”
1.1 C++对象模型
在C++中,有两种class data members:static 和 nonstatic,以及三种class member functions:static、nonstatic和virtual。在C++对象模型中:
- nonstatic data members被配置于每一个class object之内
- static data members则被存放在所有的class object之外(全局静态区)
- static被放在所有的class object之外
- nonstatic function members也被放在所有的class object之外
- virtual需要两个步骤来完成。
virtual的两个步骤支持
- 每个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table(vtbl)
- 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定和重置都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用以支持runtime type identification, RTTI)也经由virtual table被指出来,通常放在表格的第一个slot处
上图说明了C++对象模型如何应用于Point Class身上,这个模型的主要优点在于它的空间和存取时间的效率。主要缺点是:如果应用程序代码未曾改变,但所用到的class objects的nonstatic data members有所修改(有可能是增加、移除或更改),那么应用程序代码同样得重新编译。
继承关系可以指定为虚拟(virtual,也就是共享的意思):在虚拟继承的情况下,base class不管在继承链中被派生(derived)多少次,永远只会存在一个实例(称为subobject)
1.2 1.3 对象的差异
C++以下列方法支持多态:
- 经由一组隐式的转化操作。例如把一个derived class指针转化为一个指向其public base type的指针
- 经由virtual function机制
- 经由dynamic_cast和typeid运算符
多态的主要用途是经由一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。这个共享接口是以virtual function机制引发的,它可以在执行期根据object的真正类型解析出到底是哪一个函数实体被调用
需要多少内存才能表现一个class object?
- 其nonstatic data members的总和大小
- 加上任何由于aliginment的需求而填补上去的空间(可能存在于members之间,也可能存在于集合体边界)
- 加上为了支持virtual而由内部产生的任何额外负担
一个指针(引用),不管它指向哪一种数据结构,指针本身所需的内存大小是固定的。“指向不同类型的各指针”间的差异表现在其所寻址出来的object类型不同。“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小。
转型(cast)其实是一种编译器指令。大部分情况下它并不改变一个指针所含的真正地址,它只影响“被指出之内存的大小和其内容”的解释方式。
当一个base class object被直接初始化为(或被指定为)一个derived class object时,derived object就会被切割(sliced)以塞入较小的base type内存中,derived type将没有留下任何蛛丝马迹。多态于是不再呈现,而一个严格的编译器可以在编译器解析一个“通过此object而触发的virtual function调用操作”,因而回避virtual机制(提高效率)。如果virtual function被定义为inline,则更有效率上的大收获。
C++通过Class的pointer和reference来支持多态,这种程序设计风格就被称为“面向对象”(OO)
C++也支持ADT程序风格,被称为OB。如string class就是一种非多态的数据类型。这种风格速度更快(函数调用在编译期解析完成)、空间紧凑(不需要用于支持virtual的额外负担),但实际发缺乏弹性。
参考博客:https://www.cnblogs.com/lengender-12/p/6944042.html
参考书籍:《深入探索C++对象模型》侯捷