本文是对"铁道版"c++一书的知识点总结,如果侵权,请及时告知我,将尽快删去,本文禁止转载
多态性和虚函数
多态性概述
编译时的多态是通过静态连编来实现的
运行时的多态是通过动态连编来实现的
利用虚函数机制,c++可部分地采用动态连编
在c++中,编译时的多态性主要是通过函数重载和运算符重载实现的,运行时多态性主要是通过虚函数来实现的
虚函数的定义
virtual 返回类型 函数名(形参表)
{
…
};
在基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新声明定义
虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型的顺序,都必须与基类中的原型完全相同
虚函数的判断:
- 该函数与基类的虚函数有相同的名称
- 该函数与基类的虚函数有相同的参数个数及相同的对应参数类型
- 该函数与基类的虚函数有相同的返回类型或者满足赋值兼容规则的指针、引用型的返回类型
- 由于虚函数使用的基础是赋值兼容规则,而赋值兼容规则成立的前提条件是派生类从其基类公有派生
- 必须首先在基类中定义虚函数,但不必在类等级最高层类内首先声明虚函数
- 在派生类对基类中声明的虚函数进行重新定义时,关键字virtual可以写也可以不写
- 使用对象名和点运算符的方式也可以调用虚函数,但这是静态连编
- 一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性
- 虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数
- 内联函数不能是虚函数,即使虚函数在类内部定义,编译时仍将其看作是非内联的
- 构造函数不能是虚函数,但是析构函数可以是虚函数,而且通常说明为虚函数
必须使用指针才能触发virtual特性
虚析构函数
如果在主函数中用new运算符建立一个派生类的无名对象和定义了一个基类的对象指针,并将无名对象的地址赋给这个对象指针,当用delete运算符撤销无名对象时,系统只执行基类的析构函数,而不执行派生类的析构函数
virtual ~类名()
{
函数体
};
虽然派生类的析构函数与基类的析构函数名字不相同,但是如果将基类的析构函数定义为虚函数,有基类所派生的所有派生类的析构函数也都自动成为虚函数
虚函数与重载函数的关系
普通的函数重载时,其函数的参数或参数类型必须有所不同,函数的返回类型也可以不同
当重载一个虚函数时,要求函数名、返回类型、参数个数、参数的类型和顺序与基类中的虚函数原型完全相同
如果仅仅返回类型不同,其余均相同,系统会给出错误信息
若仅仅函数名相同,而参数的个数、类型或顺序不同,系统将它作为普通的函数重载,这是将丢失虚函数的特性
纯虚函数和抽象类
virtual 函数类型 函数名(参数表)=0;
纯虚函数没有函数体,他最后面的“=0”并不表示函数的返回值为0,它只是形式上的作用,告诉编译系统“这是纯虚函数”
纯虚函数不具备函数的功能,不能被调用
如果一个类至少有一个纯虚函数,那么就称该类为抽象类
由于抽象类中至少包含一个没有定义功能的纯虚函数,因此,抽象类只能作为其他类的基类来使用,不能建立抽象类对象
不允许从具体类派生出抽象类,所谓具体类,就是不包含纯虚函数的普通类
抽象类不能用作函数的参数类型、函数的返回类型或显示转换的类型
可以声明指向抽象类的指针或引用
如果派生类中没有定义纯虚函数的实现,而派生类只是继承基类的纯虚函数,则这个派生类仍然是一个抽象类,如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类,它是一个可以建立对象的具体类了