《深度探索C++对象模型》学习笔记(1-4章)

今年静下心来重读了侯捷老师译本的Lippman大神作品《Inside the C++ Object Model》,记录下学习过程中的疑问和心得有助于以后……面试。不是开玩笑,这本书里面随便找一段出来都可以当作C++面试题,学透彻了的话,无论是面试别人或者被人面试都是相当犀利的武器。

第1章 对象

对象

OOP的成本

  • 实际上相对于struct来讲,class只是程序员友好的手段
  • 单纯使用class以及继承,内存成本并不会增加,成员函数也会由编译器进行转换(4.1函数成员:调用)
  • 真正需要额外成本的是virtual特性。

对象布局方式:简单对象模型

  • 思想:尽量降低实现的复杂度
  • 每个对象中的项目都是一个slot,按照顺序排列
  • 数据成员本身并不放置在对象中,只保存指针,避免变长对象出现
  • 没有用于实际产品中(但成为指向成员的指针的灵感来源)

对象布局方式:表格驱动的对象模型

  • 对象保存两个指针,一个指向拥有所有数据成员指针的表格,一个指向拥有所有成员函数指针的表格
  • 也没用于实际产品中(但指向函数指针表格的指针,演化为vptr)

对象布局方式:C++对象模型

  • 演化自简单对象模型
  • 非静态成员存储于类内。静态的则都位于之外。
  • vptr和vtbl的概念。用于支持RTTI的type_info位于vtble第一个slot内

继承的情况

  • 简单模型:子类描述基类的slot保存基类指针,优点是父类的修改不会影响子类
  • 另一模型:保存一个基类表格,子类拥有一个bptr指向之。表中的slot再指向具体的基类

差异

关键字差异

  • class和struct的思考:为了兼容C而多做了很多工作
  • struct表现数据集合体,而class为OOP而生
  • class的多个section不能保证成员在内存中的顺序和声明的一样
  • struct目前的作用,抽取class的一部分作为参数传给C函数

对象差异

  • 三种programming paradigms
    1. procedural model,C语言的函数调用
    2. ADT model,隐含的调用,例如等号运算符
    3. object-oriented model,面向对象特性
  • 多态的实现需要由指针或引用来实现,但C++中的指针和引用并非多态的必然结果
  • 支持多态的方法
  • 指针的转换(基类子类)
  • 虚函数调用
  • dynamic_cast或者typeid运算符

指针和多态

  • void*虽然可以指向某地址,但并不清楚具体类型,也不能通过它操作对象
  • D继承自B,D的大小为B的子对象加上D特有的部分
  • D*和B*的指针对象虽然都指向同一个开始地址(B的开头),但它们涵盖的范围不同
  • 指针在编译期会决定固定的可用接口(public)以及接口对应的访问范围,这类信息都在链接(link)中,它位于vptr和其指向的vtbl之间
  • 编译器在构造和赋值时候会决定vptr的值。如果对象含有多于1个的vptr,那么就不用基类指针进行覆盖(5.4构析拷贝:拷贝赋值)

Read more >>>