第三章数据成员与继承及指向成员的指针

  

一、非多态继承

  1.派生类中每个基类的子对象都要保持其完整性,即每个子对象都与独立对象内存布局相同,都会经过alignment(会造成代码膨胀)

class Concrete1{
  public:
      //……
  private:
      int val;
      char bit1;
  };
  ​
  class Concrete2:public Concrete1{
  public:
      //……
  private:
      char bit2;
  };
  ​
  class Concrete3:public Concrete2{
  public:
      //……
  private:
      char bit3;
  };

        

   2.对象拷贝的内容根据指针类型决定,如下列代码只拷贝子对象Concrete1的内容(不论指针实际指向哪里)

Concrete1 *pc1_1,*pc1_2;
*pc1_2=*pc1_1;

 

二、多重继承

  1.自然多态:类体系中基类和派生类的对象都是从相同地址开始,如上图所示。

  2.多态地址转换:①多重继承中一般第一条继承链的对象是自然多态,基类指向派生类时只需简单赋值即可。

        ②多重继承中的其余继承链均不满足自然多态需要将指针进行转换。如下图,基类Vertex到最终派生类Vertex3d需要进行地址转换。并且当实现多态的是指针时还需要测试条件(测试是不是空指针,引用不需要,引用不能绑定到nullptr)

Vertex3d v3d;
Vertex *pv;
Point2d *p2d;
Point3d *p3d;
//第一继承链,直接拷贝地址
p2d=&v3d;
p3d=&v3d;

//引用
pv=&v3d;
//转换为
pv=(Vertex*)(((char*)&v3d)+sizeof(Point3d));
//指针
Vertex3d *pv3d;
pv=pv3d;
//转化
pv=pv3d?(Vertex*)(((char*)&v3d)+sizeof(Point3d)) :0;

 

 

三、虚拟继承

  1.传统虚拟继承模型:在每个派生类中添加一个指向基类子对象的指针

  造成的问题①每一个对象针对每一个虚基类都要产生一个指针。(类对象的内存不固定随虚基类的数量变化)

       ②访问层次增加(如果有多层虚拟派生,则访问需要经过多次指向虚基类的指针)

      

  2.现代虚拟继承模型:

  (1)解决第二个问题:将指向虚基类的指针放入到所有派生类对象当中。(空间换时间)

  (2)解决第一个问题:

    ①Microsoft引入虚基类表。类中增加一个指向虚基类表,表中存放真正的指向虚基类的指针。

    ②在虚函数表中放置虚基类的偏移offset。Sun编译器虚函数表中正值索引代表虚函数,负值索引代表虚基类的偏移。

      

 四、指向成员的指针

  1.形式: T Class::*x。其中T为类型,Class为类名,x为类Class的成员。

  2.使用:object.*x  代表访问对象object的成员x

  3.取类成员的地址:&Class::x  返回值为成员x在类对象中的偏移量offset

  4.作用可以用来确定对象在内存中的排列顺序或者内存的布局 &Class::x > &Class::y 代表x排列在y之前(若x和y在同一访问域则代表y声明在x声明之前)

  5.访问效率:未经过编译器优化时效率低于直接存取(多了一层指针的访问具有间接性)。

posted @ 2021-06-22 11:42  放不下的小女孩  阅读(63)  评论(0编辑  收藏  举报