c++中多态与多重继承实现的特殊语言障碍

  介绍

这篇文章将为大家详细讲解有关c++中多态与多重继承实现的sli,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

<强> c++多态的虚指针实现

首先讨论c++。多态也即子类对父类成员函数进行了重写(覆盖)后,将一个子类指针赋值给父类,再对这个父类指针调用成员函数,会调用子类重写版本的成员函数。简单的例子:

class  Parent1  {   公众才能:   virtual 才能;void  sayHello (), {, printf (“Hello 得到parent1 ! \ n");,}   };      class  Child : public  Parent1  {   公众才能:   virtual 才能;void  sayHello (), {, printf (“Hello 得到孩子! \ n");,}   };      int  main (), {   Parent1 才能;* p =, new 孩子();   p→才能sayHello ();,,//, get “Hello 得到孩子!“   }

首先需要明白,对于底层实现而言,成员函数就是第一个参数为对象指针的函数,编译器自动将对象指针添加到函数参数中并命名为这指针,除此之外与普通函数并无本质不同。对于非多态的成员函数调用,与非成员函数调用过程基本是一致的,根据参数列表(参数列表中包含对象指针类型)和函数名在编译时确定实际调用的函数。

为了实现多态,不能只根据对象指针类型推断函数签的名,也即例子中,<代码> p→sayHello() 这一行代码在执行时不能只根据p的类型确认调用的函数应该是<代码>父::sayHello> 孩子:sayHello>

类的虚函数表也即所有可能发生重写的函数指针表,对象创建时根据其实际类型决定其虚函数指针指向的虚函数列表。如在上文的例子中,Parent1和儿童类的虚函数列表都只有一个函数,分别是<代码> Parent1:: sayHello 和<代码>孩子::sayHello>

Parent1和孩子对象都没有自定义的数据结构。运行以下代码能够确认Parent1和孩子对象的真实数据结构大小都是8字节,也即只有虚函数列表指针。把Parent1和Child1对象作为64位整数输出,可以看到p1, p2的值相同,p3与前两者不同。这个值也即相应类的虚函数表地址。

Parent1 *, p1 =, new  Parent1 ();   时间=Parent1 *, p2  new  Parent1 ();   时间=Parent1 *, p3  new 孩子();   printf (“sizeof  Parent1: % d, sizeof 孩子:,% d \ n",   sizeof (Parent1),才能,sizeof(孩子));   printf (“val 提醒p1:, % lld \ n",, * (int64_t *) p1);   printf (“val 提醒;p2: % lld \ n",, * (int64_t *) p2);   printf (“val 提醒p3:, % lld \ n",, * (int64_t *) p3);

<强> c++多态与多重继承

有一个非常有意思的问题:c++发生多重继承时,如何支持多态。刚刚提到,多态的原理是编译器将成员函数调用编译为“引用虚函数表中第N个函数”,虚函数表在对象数据结构中的位置和要调用虚函数列表中的第几个函数在编译时都是需要确定的。多重继承对象如果只有一个虚函数列表,那不同父类的虚函数列表中的位置就要发生冲突。如果有多个虚函数列表,编译时就难以确定虚函数列表指针在数据结构中的位置C + +采取了非常精妙的做法:将所有父类的数据结构(包括虚指针列表)在该对象的数据结构上依次排列,该对象的指针正常指向数据结构起始位置。<强>当指针发生类型转换时,c++编译器会对指针的值尽可能的进行调整,使其指向该指针类型应该对应的位置。指针的值在这个过程中发生了变化

比如,儿童类继承了Parent1, Parent2两……个类,则在孩子指针转换为Parent1指针时,不对指针的值进行调整,因为Parent1是孩子的第一个父类,但将孩子转换为Parent2时……,需要将指针指增加Parent1数据结构长度的值,使指针指向对应Parent2数……据结构开始位置。在本例子中,Parent1数据结构只有虚函数列表指针,在64位机器上长度为8。因此,在孩子指针转换为Parent2指……针时,其值增加了8。

 class  Parent1  {
  公众才能:
  virtual 才能;void  sayHello (), {, printf (“Hello 得到parent1 ! \ n");,}
  };
  
  class  Parent2  {
  公众才能:
  virtual 才能;void  sayHi (), {, printf (“Hi 得到Parent2 !……\ n");,}
  };
  
  class  Child : public  Parent1, public  Parent2  {
  公众才能:
  virtual 才能;void  sayHello (), {, printf (“Hello 得到孩子! \ n");,}
  virtual 才能;void  sayHi (), {, printf (“Hi 得到孩子! \ n");,}
  };
  
  int  main (), {
  Child 才能;* p =, new 孩子();
  ,,printf (“size  of 孩子:,% d",, sizeof(孩子));
  ,,printf (“pointer  val  as 孩子*:,% lld \ n",, int64_t (p));
  ,,printf (“pointer  val  as  Parent1 *:, % lld \ n",, int64_t (p (Parent1 *)));
  ,,printf (“pointer  val  as  Parent2 *:……, % lld \ n",, int64_t ((Parent2 *)……p));
  null

c++中多态与多重继承实现的特殊语言障碍