深度探索c++对象模型1

  • C++的主要额外负担:
    • virtual function 机制
    • virtual base class 用以实现“多次出现在继承体系中的base class,又一个单一而被共享的实例”
    • 多重继承下的额外负担
1.1 C++对象模式
  • C++对象模型

    • 非静态成员变量存放在每一个class object里面,静态成员变量存放在个别的class object 之外;静态函数,非静态函数成员放在个别的class object之外,虚函数特殊对待:
      • 每一个class 产生出一堆指向virtual function 的指针,放在表格中,这个表格称之为虚函数表(virtual table)
      • 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针称为$vtpr$.$vtpr$的设定由每一个class的constructor,destructor和copy assignment运算符自动完成。每一个class所关联的$tyle_info$ object(用来支持runtime type identification)也经由虚函数表纸出来,通常放在表格的第一个slot里面。
        例子如下
        Alt
        Alt
  • C++继承

    • 使用所谓的base table 模型。每一个class object内涵一个bptr,被初始化,指向它的base class table,然后这个表就如同虚函数表一样指向继承的类的对象,如下图
      Alt
      Alt
  • 什么时候一个人应该使用struct 取代class?当它让一个人感觉比较好的时候(狗头)
    聚合(composition)而非继承才是把C++和C结合起来的好方法。
    struct在C++中的一个合理用途,是当你要传递一个“复杂的class object的全部或者部分”到某一个C函数去的时候,struct声明可以将数据封装起来,并且保证拥有与C兼容的空间布局,然而这种保证只在聚合(composition)的情况下存在。如果是继承的话,可能会因为内存布局原因无法实现想要的结果。

  • C++以下列方法支持多态:

    • 经过一组隐式的转化操作,比如把一个派生类的指针转化为一个指向它的public base type的指针:
      shape *ps=new circle ();
    • 经由virtual function机制:
      ps->rotate()
    • 经由$dynamic_cast$和typeid运算符:
      $if(circle pc=dynami_cast < circle>(ps))$
  • 需要多少内存才能够表现一个class object:

    • 非静态成员变量的总和大小
    • 加上任何由于alignment(对齐)的需求而填补(padding)上去的空间
    • 加上为了支持virtual而内部产生的任何额外负担
  • 关于指针:
    不同类型的指针从内存需求的观点来看没有什么不同,“指向不同类型之各指针‘间的差异,既不在其指针表示法的不同,也不再其内容的不同,而是在其所寻址出来的object类型不同。也就是说,“指针类型”会教导编译器如何解释某一个特定地址的内存内容及其大小。

  • 最后一部分内容讨论了多态发生的条件,我认为总结下来就是引用和指针可能触发多态,通过虚函数来实现。然后将子对象赋值给父类对象一般会导致切割,来放置数据溢出。

  • 具体问题:

    • 一个Bear指针和一个ZooAnimal指针有什么不同:

      1
      2
      3
      Bear b;
      ZooAnimal *pz=&b;
      Bear *pb=&;

      它们每一个都指向Bear object 的第一个type,它们的区别是:pb所涵盖的地址包含整个 Bear object但是pz所涵盖的地址之包含Bear object中的ZooAnimal subobject.
      内存布局如下图:

      Alt
      Alt