C++类的类型只有两类,多态类型和非多态类型。前者是有虚函数的类型,以下重点介绍多态和与多态联系紧密的虚函数。
-
多态概述
同样的消息被不同类型的对象接收时导致的不同行为。
消息:对类成员函数的调用,不同行为:调用不同的函数。
举例:运算符就是一种多态,比如“+”,消息就是相加的操作,不同的行为就是两个整数相加或者一个浮点数和一个整数相加(需要类型转换)是不同的行为。 -
多态类型
多态有四种类型:重载多态,强制多态,包含多态,参数多态。
前两种统称专用多态,后两种统称通用多态。
举例:普通函数的重载是一种重载多态,类型的强制转换是一种强制多态,通过虚函数实现同名的不同函数调用是包含多态,用类模板对不同类型参数操作是参数多态。 -
多态实现
分为两类:编译时的多态和运行时的多态
分类依据是是在编译过程还是在运行过程确定的同名函数的具体操作对象。
确定具体操作对象也就是把一条消息和一个对象的方法相结合的过程叫绑定。绑定可以分为静态绑定和动态绑定,分类依据和多态分类一样,在编译连接阶段完成绑定的叫静态绑定,在程序运行阶段绑定的叫动态绑定。 -
多态表现形式
主要有两种形式分别针对指针和引用:
1.派生类的指针可以赋值给基类的指针
通过基类指针调用基类和派生类的同名虚函数时:若该指针指向一个基类对象,那么被调用的是基类的虚函数,如果指向一个派生类对象,被调用的是派生类的虚函数
2.派生类的对象可以赋给基类引用
通过基类引用调用基类和派生类的同名虚函数时:若该引用引用的是基类的对象,被调用的是基类的虚函数,若该引用引用的是一个派生类的对象,被调用的就是一个派生类的虚函数 -
虚函数
虚函数有以下特性:
在类的定义中,前面有virtual关键字的成员函数就是虚函数
虚函数是动态绑定的基础
虚函数必须是非静态函数
虚函数经过派生之后就可以实现运行过程的多态
虚函数的声明只能出现在类定义的函数原型声明中,不能在成员函数实现的时候
不能声明虚构造函数,但是能够声明虚析构函数
派生类虚函数覆盖基类虚函数,同时还要隐藏基类虚函数的其他重载行驶
运行过程中的多态需要满足三个条件:
1.满足赋值兼容规则
2.声明虚函数
3.由成员函数调用或是通过指针或引用来访问虚函数
(复习一下赋值兼容规则,也叫类型兼容规则。定义是:在需要基类对象的任何地方都可以用共有派生类对象代替。(派生类对象当做基类对象用的时候只能使用从基类继承的成员)这个规则具体分为三点:①派生类的对象可以隐含转换为基类的对象。②派生类的对象可以初始化基类的引用。③派生类的指针可以隐含转换为基类的指针。)
派生类没有给出显式声明时,判断派生类的一个函数成员是否是虚函数根据三点:
1.该函数与基类虚函数有相同的名称
2.该函数与基类虚函数有相同的参数个数和相同的参数类型
3.该函数与基类虚函数有相同的返回值或满足赋值兼容规则的指针、引用的返回值 -
纯虚函数
纯虚函数的相关特性:
纯虚函数的声明格式是 virtual 函数类型 函数名(参数表)= 0,也就是在虚函数声明后面多了=0
声明了纯虚函数之后,基类可以不给出函数实现部分
带纯虚函数的类是抽象类
抽象类不能实例化(不能定义抽象类的对象,但是可以定义抽象类的指针和引用)