【探索c++对象模型】笔记总结

1.多态的作用是什么?

       多态的主要用途是经由一个共同的接口来影响类型的封装。这个接口一般定义在一个抽象的class object当中,由virtual function 机制引发,它可以在执行期间根据object的真正类型解析出到底使用的是哪一个函数实体。

2.哪些方式支持多态?

  • 经由一组隐含的转化操作。例如将一个derived class指针转化为一个base class指针。
  • 经由virtual function机制
  • 经由dynamic_cast和typeid的运算符

3.一个class object多少内存?

  • 所有nonstatic data member的大小
  • 由于alignment字节对齐所补上去的空间
  • 为了支持virtual内部产生的额外负担,如vptr

4.产生nontrivial default constructor的四种情况

  • 带有“default constructor"的member class object
  • 带有”default constructor"的base class
  • 带有一个”virtual function"的class
  • 带有一个”virtual base class"的class

5.不展现bitwise copy 语义,合成copy constructor的四种情况

  • 带有“copy constructor"的member class object
  • 带有”copy constructor"的base class
  • 带有一个”virtual function"的class,这种情况会增加一个virtual function table ,并重新设定vptr
  • 带有一个”virtual base class"的class,这种情况会设定virtual base class pointer/offset的初值

6.class constructor的初始化次序:

  1. 首先判断如果有virtual base class,有多个则按照从左到右,从深到浅的次序初始化
    1. 使用member initialization list 初始化virtual base class,如果有参数需要传递则必须传递
    2. 不在list中,但virtual base class有default constructor,则使用default constructor初始化
    3. class中每一个virtual base class subobject 的偏移量offset,必须在执行期可被存取
  2. 然后判断如果有nonvirtual base class,有多个则按照base class的声明次序初始化
    1. 使用member initialization list 初始化base class,如果有参数需要传递则必须传递
    2. 不在list中,但base class有default constructor,则使用default constructor初始化
    3. 当初始化第二个及后继的base class时,this指针需要调整
  3. 初始化每一个vptr,将其指向适当的virtual function table
  4. 初始化member成员变量,有多个则按照member声明次序初始
    1. 使用member initialization list 初始化member,与list的顺序无关,还是按照member声明次序初始化
    2. 不在list中,但member有default constructor,则使用default constructor初始化

7.什么时候必须使用member initialization list初始化?

  • 当初始化一个reference member
  • 当初始化一个const member
  • 当有一个base class,并且它由一组参数
  • 当有一个virtual base class,并且它有一组参数

8.空类的sizeof多少?

       sizeof的大小是1 byte

       那是编译器按插进去的一个char,可以使这个class的两个实体在内存中得以分配独一无二的地址

9.data member的存取?

  • static data member
    • 位置:放在class之外,存放在data segment当中
    • 实体:只有唯一一个实体
    • 存取:不由this指针存取
    • 取地址:会得到一个指向其类型数据的指针,而不是一个指向class member的指针
  • nonstatic data member
    • 位置:存放在class之中
    • 存取:由this存取,并且编译器需要把class object的起始地址,加上class member的偏移量offset(=&Point::x-1)
    • 取地址:得到一个指向class data member的指针,其offset值总是被加上1

10.继承中的data member 的内存模型

  • 单一继承,不含virtual functions
float x
float y

 

float x
float y
float z
  •  
  • 单一继承,含有virtual functions
float x
float y
__vptr_A

 

float x
float y
__vptr__A
float z
  • 多重继承
float x
float y
__vptr_A

 

float x
float y
__vptr__A
float z

 

C *next
__vptr_C

 

float x
float y
__vptr__A
float z
C *next
__vptr_C
float q

 

            注意:对于一个多重继承对象,将其地址指向给第一个base class的指针,其情况和单一继承一样,具有相同的起始地址

                      但将其地址指向给第二个base class及后继类型的指针,其地址需要修改

  • 虚拟继承
float x
float y
__vptr__A

 

float z
A *ptrA
__vptr__B
float x
float y
__vptr__A

 

C *next
A *ptrA
__vptr__C
float x
float y
__vptr__A

 

float z
A *ptrA
__vptr__B
C *next
A *ptrA
__vptr__C
float more
float x
float y
__vptr__A

 

       注意:virtual base class offset偏移量存放在virtual function table中,以负值索引存取

11.member functions 的调用方式

  • nonstatic member functions
    • 内化为static member function:
    1. 安插一个额外this指针
    2. 对每一个nonstatic data member的存取操作均由this指针存取
    3. member function 重写为一个外部函数(mangling)
  • virtual member functions:会通过vptr调用virtual table中根据索引值取对应的虚函数,函数参数含this指针
  • static member functions

12.active virtual function

  • (激活一:)继承自base class的函数实体,即derived class 决定不override的情况下
  • (激活二:)这个class自己定义的函数实体,即derived class 决定override的情况下
  • (激活三:)pure_virtual_called()函数实体,既可以当纯虚数,也可以当作执行器异常处理函数

13.对于virtual function的调用,在编译时期可知:

  • 我们不知道ptr所指的对象的真实类型,但是我们知道通过ptr能够存取对象的virtual table
  • 我们不知道哪个类型的函数实体x()被调用,但是我们知道每一个x()函数地址都会放在slot索引值为n的槽中

14. virtual function的内存模型

  • 单一继承
    • (激活一:)base class的函数实体地址拷贝到derived class的virtual table相对应的slot当中
    • (激活二:)overriding的函数实体地址必须放置对应的slot当中
    • 自己加入一个新的virtual function,此时virtual table增大一个slot,新的函数实体地址会存放在这个slot当中
  • 多重继承:
    • 对于多重继承,一个derived class会产生n-1个额外的virtual table(n为base class的数量),分为:
      • 主要表格,与base1共享
      • 次要表格,与base2有关
    • 必要的this指针调整
      • 当一个base2 class的指针指向一个derived class的对象时,被处理的是次要表格(base2 class类),由于调用的是derived class的virtual function,在调用之前this指针指向的是base2 subobject的位置,先要将指针调整至derived对象的起始处
      • 当一个derived class的指针指向一个derived class的对象时,被处理的是主要表格(derived class类),由于调用继承自base2 class的virtual function,在调用之前this指针指向的是derived对象的起始处,先要将指针调整至base2 subobject的位置
  • 虚拟继承
    • 对于继承体系中的virtual base class,每一个derived class都有一个virtual table存放了virtual base class subobject距离derived对象起始处的偏移值offset,并且将它存放在virtual table中以负数为索引的slot中

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值