C++ 基础 --多态

C++--多态

  • 多态
    • 多态的概念
    • 多态的定义
      • 虚函数
      • 虚函数的重写
      • 虚函数重写的两个例外
    • C++11 override 和 final
    • 重载、重写(覆盖)、隐藏(重定义)对比

多态

多态的概念

当完成某个行为时,不同的对象去完成,会有不同的状态

举个小栗子:买票这个行为,学生买会有打折,普通人买全价票,军人可以优先购票 —多态性为

多态分为静态多态和动态多态,其中静态多态就是我们所熟知的函数重载。这里静态的含义是指:在编译期间完成的事件
而我们今天主要了解的是动态多态,也就是在进程运行期间的多态。

多态的定义

多态是不同继承关系的类对象,去调用同一函数,产生的不同行为状态。
比如Student 继承了 Person , student对象半价,person全价。

在继承中,构成多态有两个条件:

  • 必须要用基类指针或者引用调用虚函数
  • 被调用的函数必须是虚函数,且派生类 必须要对基类的虚函数进行重写
    C++ 基础 --多态_第1张图片

这里提到了几个概念,我们来一一解答

虚函数

虚函数:就是被virtual修饰的类成员函数
C++ 基础 --多态_第2张图片
这里我们还需要注意几点:

  • 此处虚函数的virtual 与我们前面虚继承的virtual ,没有任何关系。虚继承是为了消除二义性与代码数据冗杂。而虚函数是为了实现多态。
  • 只有非静态类成员函数可以被virtual修饰,成为虚函数。

虚函数的重写

虚函数的重写,也叫做虚函数的覆盖,在派生类中,有一个跟基类完全相同的虚函数(返回值类型、函数名、参数列表完全相同),称为子类的虚函数重写了基类的虚函数
C++ 基础 --多态_第3张图片

此处有一个小小的细节,我们在写派生类的虚函数时,可以不给这个虚函数加virtual ,因为继承后,基类的虚函数被继承下来,在派生类依旧保持着虚函数的属性。但显然这是很不规范的。

虚函数重写的两个例外

  • 协变
    协变是指:基类与派生类虚函数的返回值类型不同,具体是指,基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用。
    C++ 基础 --多态_第4张图片

  • 析构函数的重写

基类与派生类析构函数的名字不同,此时如果基类的析构函数为虚函数,派生类只要析构函数定义了,无论是加没加virtual,两个析构函数都构成了重写。因为在编译期间,析构函数的函数名都会被替换成destructor。实质上他们还是同名的,并不违背函数重写的条件。

我们简单看一个例子:
C++ 基础 --多态_第5张图片
我们这里p1 和 p2 都是基类型指针,指向父子对象。此时我们没有采用虚函数,也就是说并没有构成多态,此时当我们delete两个指针时,他调用的都是父类的析构函数和delete,这是为什么呢?因为我们在之前继承中了解到,析构函数都是同名的,那就会构成隐藏,如果我们想要调用可以采用作用域限定符。
当然我们还是希望他们可以以多态的形式出现
C++ 基础 --多态_第6张图片
此时的析构函数重写了,就构成了多态,调谁就析构谁。

此处有一个细节,子类会自动调用自己的析构函数,再去自动调用父类的析构函数。
我们尽量不要使用这种特列,这太不利于维护了。

C++11 override 和 final

我们都知道,是否形成多态需要程序运行起来,我们才能判断。所以c++11给了两个检查语法的关键字

final :修饰虚函数,表示该虚函数不能再被重写

C++ 基础 --多态_第7张图片
override:检查派生类虚函数是否重写了某个基类的虚函数,如果没有重写,则编译报错

C++ 基础 --多态_第8张图片


重载、重写(覆盖)、隐藏(重定义)对比

C++ 基础 --多态_第9张图片

重写(覆盖)是重定义(隐藏)的一种特殊情况

你可能感兴趣的:(C\C++,基础语法,c++,多态,虚函数,重定义,重写)