如果子类定义了与父类中原型相同的函数会发生什么——

函数重写 

在子类中定义与父类中原型相同的函数
函数重写只发生在父类与子类之间
 
重载与重写区别:
重载:同一个作用域;
      子类无法重载父类函数,父类同名函数将被覆盖;
      重载是在编译期间根据参数类型和个数决定;
重写:发生于父类、子类之间;
      父类和子类函数有相同的函数原型;
      使用virtual关键字声明后能够产生多态;
      运行期间根据具体对象类型决定调用的函数。

面向对象中的多态

6.多态

C++中通过virtual关键字对多态进行支持
使用virtual声明的函数被重写后即可展现多态特性

 

多态成立的三个条件

1.继承    2.虚函数重写    3.父类指针指向子类对象

静态联编和动态联编

1、C++与C相同,是静态编译型语言
2、在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象;所以编译器认为父类指针指向的是父类对象。
3、由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象
从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数。这种特性就是静态联编。

动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟绑定)。
switch 语句和 if 语句是动态联编的例子。

 

虚析构函数

虚析构函数:通过父类指针释放子类对象

 

在什么情况下应当声明虚函数
构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数
 析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象 

 

多态

原理

  • 当类中声明虚函数时,编译器会在类中生成一个虚函数表
  • 虚函数表是一个存储类成员函数指针的数据结构
  • 虚函数表是由编译器自动生成与维护的
  • virtual成员函数会被编译器放入虚函数表中
  • 当存在虚函数时,每个对象中都有一个指向虚函数表的指针(C++编译器给父类对象、子类对象提前布局vptr指针;当进行函数调用时,C++编译器不需要区分子类对象或者父类对象,只需要再base指针中,找vptr指针即可。)
  • VPTR一般作为类对象的第一个成员 


说明1:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
说明2:
出于效率考虑,没有必要将所有成员函数都声明为虚函数
说明3 :
C++编译器,执行run函数,不需要区分是子类对象还是父类对象

 

构造函数中调用虚函数不能实现多态——构造的顺序是先构造父类再构造子类,当调用父类构造函数时,虚函数指针vfptr指向父类的虚函数表,而当调用子类构造函数时,虚函数指针 vfptr 指向子类的虚函数表

 

父类指针指向子类数组时,由于父类和子类的数据长度不同,导致父类指针的步长短于子类,所以如果用父类指针指向子类数组,访问时会出现内存错误,即段错误。

 

纯虚函数和抽象类

  • 纯虚函数是一个在基类中说明的虚函数,在基类没有定义,要求任何派生类中都必须定义自己的版本。
  • 纯虚函数为各派生类提供一个公共界面(接口)。
  • 纯虚函数说明形式

                                 virtual   类型    函数名(参数表) =  0

  • 一个具有纯虚函数的基类成为抽象类

抽象类的概念:

1.含有纯虚函数的类

2.抽象类不能用于直接创建对象,但可以声明抽象类的指针或引用

3.可使用指向抽象类的指针支持运行时多态性

4.派生类中必须实现基类中的纯虚函数,否则它仍将被看作一个抽象类

 

 

 

相关文章:

  • 2022-12-23
  • 2021-10-17
  • 2022-12-23
  • 2021-10-11
  • 2022-12-23
  • 2022-12-23
  • 2021-04-16
猜你喜欢
  • 2022-02-02
  • 2021-09-24
  • 2021-06-24
  • 2022-01-21
  • 2021-11-21
  • 2021-09-07
  • 2022-12-23
相关资源
相似解决方案