一、多态的概念
二、多态的定义和实现
三、虚函数
3.1 虚函数的定义
3.2 虚函数的重写
3.3 重写的特例
3.4 override和final(C++11)
3.5 重载、重写和隐藏
三、抽象类
3.1 概念
3.2 接口继承和实现继承
四、多态的原理
4.1 虚函数表
4.2 虚函数表的作用
4.3 用程序打印虚表
五、多继承中的虚函数表
一、多态的概念
多态,即多种形态,也就是当不同的对象去执行相同的接口时会产生不同的状态。
多态是面向对象编程领域的核心概念之一,可以简单的概括为“一个接口,多种方法”。
例如被饱受诟病的“杀熟”行为,新用户的折扣和概率高,而老用户的折扣和概率低,同样的商品或活动,两个群体得到的结果不同,这也是一种多态行为。
二、多态的定义和实现
不同继承关系的类对象,去调用同一个函数,产生了不同的结果,这就是多态。
例如我们定义一个Person类,Person对象买票要付全价。再定义一个继承Person类的Student类,Student对象买票只需要半价,这两个对象在买票时都要调用BuyTicket函数。怎么去实现这个多态呢?结果如下:
可以看到,虽然BuyTicket函数的形参类型是Person的引用,但是当我们传入Student类对象时还是可以调用到Student类的成员函数。
这里引出在继承中构成多态的两个条件:
- 必须通过基类的指针或引用来调用
例如BuyTicket函数中的参数就是Person类对象的引用,而Person类在继承关系中为基类
如果不用指针或引用就无法构成多态,例如:
- 被调用的函数必须是虚函数,并且派生类中需要对基类的虚函数进行重写
何为虚函数,何为重写?
三、虚函数
3.1 虚函数的定义
通过前面的例子可以了解到,被 virtual 修饰的类成员函数称为虚函数。
虽然和虚继承有着一样的关键字和相似的名字,但是二者并没有关系
3.2 虚函数的重写
如果派生类中的一个虚函数与基类中的某虚函数完全相同(返回值类型、函数名和参数列表都完全相同),则称子类的虚函数重写了基类的虚函数。
可以理解为,派生类继承了基类虚函数的声明,重写了其实现方式。
例如上面的例子,在Person类和Student类中有一个完全相同的price虚函数,此时即构成重写。
需要注意,在重写虚函数时即使派生类的虚函数不加virtual关键字,也可以构成重写
因为基类的虚函数在继承到派生类后依旧保持虚函数的属性。
但是这种写法不够规范,不推荐使用
3.3 重写的特例
(1)协变
基类与派生类的虚函数返回值类型不同的情况称为协变。
前提是两个虚函数返回的必须是父子关系的指针或引用
例如:
(2)析构函数的重写
如果将基类的析构函数定义为虚函数,那么派生类的析构函数一定会与基类的析构函数构成重写
即使它们函数名不同。
前面的文章中也提到过,编译器会将析构函数的名称统一处理成destructor,所以符合重写规则
关于析构函数的重写,还有一些需要我们知道的事,例如:
class Person { public: ~Person() { cout
- 被调用的函数必须是虚函数,并且派生类中需要对基类的虚函数进行重写