【C++】对象模型

前言

  对于传统结构化语言,如C语言,虽然编译器在背后也做了一下事情,但是很好理解。如编译器堆栈建立、参数排列、返回地址、堆栈清楚等。而对于面向对象的语言,编译器背着我们做了太多,如构造函数、析构函数、虚函数、继承、多态、合成额外函数、扩张我们函数的内容等。

  不同的对象模型会有不同的执行效率,因为编译器会根据对象模型对程序做不同的改写。

 

C++对象模型

  有如下三种:

 模型一重要!

   一个class对象需要多少内存呢,一般是一下几点的和:

  • nonstatic数据成员的大小之和;
  • 加上由于对齐而产生的填补(与机器有关);
  • 加上为了支持virtual而增加的额外负担(与编译器有关 )。

   另外值得注意的是一个没有nonstatic的类的对象的大小是1,这是被编译器安插的一个char类型,为了让该类的每个对象具有独一无二的内存地址。

 模型二

 模型三

C++的继承

  • 单继承:如图 class ostream: public ios{...};
  • 多继承:如左图 class iostream: public ostream, public istream{...};此处的需注意,若以图中的继承关系,我们会发现iosteam对象中有两份ios的对象部分,为了解决这个问题就需要virtual base class,也就是虚继承。 
  • 虚继承:如右图 class ostream: virtual public ios{...}; class istream: virtual public ios{...}; 这样无论virtual base class 在继承链中出现多少次,都只会出现一个实体。

 

 

 

   那么加上继承后,derived class object的对象模型是什么样的呢,该如何表现出base class subobject呢?有如下几种模型:

 模型一重要!

  • 对于base class object的nonstatic 数据成员,一般直接放置在derived class object中。
  • 在virtual bass class的原始模型是在class object中为每一个有关联的virtual Base class 加上一个指针。引入对于virtual base class后,对象模型为了维护每一个virtual base class的位置,不是导入一个virtual base class table,就是扩充已存在的virtual table。

   如

 

 

 

 

 

 

 模型二

  基于简单模型,增加一个slot,里面存放父类的实体的地址。

 

 

  模型三

  每一个子类对象内含一个地址bptr(类似于vptr),指向一个base class table(其中的每个slot对应一个base calss subobject)。

 

 

 

 

C++的多态

  在C++中,多态只存在于public的继承体系中。C++用下列方法来支持多态:

  1. 经由一组隐含的转换操作,如把一个derived class指针转化为一个指向其public base 类型的指针。
  2. virtual function机制;
  3. dynamic_cast和typeid运行算符。

    另外指针是C++多态的必要条件

 

空类型

  1、一个没有任何数据成员和成员函数的类型的sizeof是1,因为如果我们要使用一个类型的实例,该实例必须在内存中占用一定的空间,否则无法使用。,当然大小也可以比1大,具体由编译器决定。

  2、当在1的基础上,加上非虚成员函数后,sizeof还是不变。

  3、当在1的基础上,加入虚函数后,由于此时需要以指向虚函数表的虚指针,所以sizeof为指针的大小,32位机为4字节,64位机为8字节。

 

其他知识点

C语言中,数据和函数(对数据的操作)是分开的。

  C++同时支持OB和OO两种设计。

  OB :Object Based ,非多态的数据封装模型,就是ADT(Abstract Data Type)的概念,提供了类型对象的一些接口和操作。

  OO :Object Oriented ,支持多态,需要virtual的支持,这导致了内存布局和存取时间上的额外负担。virtual机制包括virtual function机制(用以支持执行期动态绑定),virtual base class (用以实现“对此出现在继承体系中的base class,有一个单一而被共享的实体”)。

 

  C++中struct和class的用法基本一样,只是继承和成员的默认权限不同,class默认是private继承和private成员,而struct默认是public继承和public成员。

 

  指针:指针的值是所指对象的首地址,偏移量有指针类型决定。base class的指针可以指向继承体系中的任一类型的对象。

 

参考

     《深度探索C++对象模型》

  怀安散人《深度探索C++对象模型》 读书心得 Chapter1

  怀安散人《深度探索C++对象模型》 读书心得 Chapter2

 

posted @ 2020-06-10 22:44  Chen沉尘  阅读(391)  评论(0编辑  收藏  举报