C++对象模型学习

更新记录

时间 | 更新记录 |
---|---|---
2020年4月6日| 初稿 |

背景

  • 自从转入iOS,学习到iOS的方法调度,runTime的知识,了解了一下iOS的对象模型。
  • 为了对iOS有更深入的了解,也对之前所学习的C++做一些补充,特此先学习一下C++的对象模型(说来也惭愧,windows开发一年半,没有看到C++对象模型相关的书或者网文)

三种对象模型

简单对象模型

  • 所有的成员变量、成员函数都作为对象在内存中的一部分
  • 简单、粗暴
  • 缺点:占用内存大,以生成对象个数线性递增。
    • 函数是所有对象共用,其实没有必要每个对象都记录,可以统一到某个地方。

表格驱动模型

  • 区分数据成员和函数成员
  • 对象只存放数据表指针和函数表指针,所以对象内存固定
    • 针对于简单对象模型,表格驱动模型把数据成员列表作为每个对象独有的内存数据,而成员函数表则作为所有对象共享的内存数据,即可以解决简单对象模型“占用内存多”的问题
  • 缺点
    • 无法支持多态(确切地说,支持起来就比较复杂或者麻烦)
    • 查找数据成员时,较第一种方案多了一次寻址。而且每个对象都多了一个表格指针,内存升高了。
      • (要知道C++可是非常重视性能的,每次查找数据成员都要多一次寻址,而数据成员可能用的很多)
    • 调用成员函数时,较第一种方案多了一次寻址。
      • 同上,C++的成员函数也可能调用的很频繁

当前的C++对象模型

  • 对象第一个字节(32位系统下)存储虚函数表指针(如继承树上有虚函数)
    • 虚函数一律放入虚函数表中,通过表格进行查找
    • 虚函数表的第一个slot存放type_info,用以支持RTTI
  • 后续依次存放父类到子类的(非静态)数据成员变量
  • 成员函数和全局函数类似,存放在代码区,不存储在对象相关内存中。
  • 优点
    • 查找数据,直接根据基地址+偏移量进行查找即可
    • 支持多态较简单
    • 成员函数调用快,直接根据符号寻址即可调用。相比表格驱动模型,不必多寻址一次。

方法调度

  • 虚函数调用
    • 这也是面试中的高频考点
    • 通过实际的对象指针(即this指针),查找虚表,调用虚表中对应的函数。
    • 编译时所作工作
      • 将父类的虚函数和子类的虚函数进行逻辑判断,确定子类的虚函数表中存放的虚函数,是父类的虚函数实现,还是子类的虚函数实现
    • 运行时所作工作
      • 子类对象实际调用虚函数时,在运行时查找虚函数表,才知道调用的是哪个函数(是父类的,还是子类的)
  • 普通成员函数调用
    • 和全局函数调用类似
    • 注意:成员函数名必定不会冲突。
      • 因为普通成员函数的第一个参数是this指针,即使不同的类,普通成员函数名相同,函数参数也不同。

参考资料

posted @ 2020-04-06 13:05  HelloWooo  阅读(160)  评论(0编辑  收藏  举报