object转成实体对象_深度探索C++对象模型:三种对象模型

491b4c8f96bf6697c4fe1a7ce0634e4f.png

引言

现在有一个 Point 类,声明如下:

class Point {
 public:
  Point(float xval);
  virtual ~Point();

  float x() const;
  static int PointCount();

 protected:
  virtual ostream& print(ostream &os) const;

  float _x;
  static int _point_count;
};

这个类在机器上是通过什么模型来表示的呢?下面就介绍三种不同的实现方式。转载请注明出处:单刀土豆

1. 简单对象模型

简单对象模型名副其实,十分简单。在简单对象模型中,一个 object 是由一系列 slots 组成,每个 slot 相当于一个指针,指向一个 membermemebers 按照声明的顺序与 slots 一一对应,这里的 members 包括 data membersfunction members 。如果将简单对象模型应用在 Point Class 上,结构图如下:

17bf7659af5b27e0716b309fbd28c461.png
  • 优点:十分简单,降低了编译器设计的复杂度。
  • 缺点:空间和时间上的效率降低。由于所有 member 都对应一个 slot 指针,所以每个 object 在空间上额外多出: member's number 乘以指针大小 的空间。同时由于访问 object 的每个 member 都需要一次 slot 的额外索引,所以在时间的效率也会降低。

2. 表格驱动对象模型

表格驱动对象模型将 member datamember function 分别映射成两个表格 member data tablefunction member table ,而 object 本身只存储指向这两个表格的指针。 其中 function member table 是由一系列的 slot 组成,每个 slot 指向一个 member function ; member data table 则直接存储的 member data 本身。如果将表格驱动对象模型应用在 Point Class 上,结构图如下:

aa420648ab14367b5c3e40313a780e48.png
  • 优点:采用两层索引机制,对 object 变化提供比较好的弹性,在 objectnonstatic data member 有所改变时,而应用程序代码没有改变,这时是不需要重新编译的。
  • 缺点:空间和时间上的效率降低,具体原因可以参考简单对象模型的缺点分析。

3. C++ 对象模型

Stroustrup 早期设计的 C++ 对象模型是从简单对象模型改进而来的,并对内存空间和存取时间进行了优化。主要是将 nonstatic data members 存储在每一个 object 中,而 static data members 以及所有的 function members 被独立存储在所有 object 之外。对虚函数的支持主要通过以下几点完成的:

  • 所有包含虚函数或者继承自有虚函数基类的 class 都会有一个 virtual table ,该虚函数表存储着一堆指向该类所包含的虚函数的指针。
  • 每个 class 所关联的 type_info object 也是由 virtual table 存储的,一般会存在该表格的首个 slottype_info 用于支持 runtime type identification ( RTTI )。

如果将 C++ 对象模型应用在 Point Class 上,结构图如下:

750bbf1cca1ca3138e0c4df74c6455ba.png
  • 优点:空间和存取效率高,所有 static data members 以及所有的 function members 被独立存储在所有 object 之外,可以减少每个 object 的大小,而 nonstatic data members 存储在每一个 object 中,又提升了存取效率。
  • 缺点:如果应用程序的代码未曾更改,但所用到的 classnonstatic data members 有所更改,那么那些代码仍然需要全部重新编译,而前面的表格驱动模型在这方面提供了较大的弹性,因为他多提供了一层间接性,当然是付出了时间和空间上的代价。

在加上继承情况下的对象模型

C++ 支持单继承、多继承、虚继承,下面来看下 base class 实体在 derived class 中是如何被构建的。

简单对象模型中可以通过 derived class object 中的一个 slot 来存储 base class subobject 的地址,这样就可以通过该 slot 来访问 base class 的成员。这种实现方式的主要缺点是:因为间接性的存储而导致空间和存取时间上存在额外负担;优点是: derived class 的结构不会因为 base class 的改变而改变。

表格驱动对象模型中可以利用一个类似 base class table 的表格来存储所有基类的信息。该表格中存储一系列 slot ,每个 slot 存储一个 base class 的地址。这种实现方式的缺点是:因为间接性的存储而导致空间和存取时间上存在额外负担;优点是:一是所有继承的 class 都有一致的表现形式(包含一个 base table 指针,指向基类表)与基类的大小和数目没有关系,二是 base class table 增加了子类的扩展性,当基类发生改变时,可以通过扩展、缩小或者更改 base class table 来进行调整。

以上两种实现方式都存在一个重要的问题,就是由于间接性而导致的空间和时间上的额外负担,并且该间接性的级数会随着继承的深度而增加。

C++ 最初采用的继承模型并不采用任何间接性,所有基类的数据直接存储在子类当中,这样在存储结构和访问效率上是最高效的。当然也有缺点:当 base class members 有任何改变,用到此 base class 或者 derived class 的对象必须重新编译。在 C++ 2.0 引入了 virtual base class ,需要一些间接性的方式来支持该特性,一般会导入一个 virtual base class table 或者扩展已有的 virtual table ,详细会在后面博文讨论。

8b7244452a746b7c4fc138a417e855fb.png

75988e9ff22fc23f5acfe5a443461838.png

b45639effa90667de3de9d2d27f6675c.png

点击链接领取资料,先到先得:

点击链接:领取新手礼包,学习资料​jq.qq.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值