多态性(polymorphism),
从系统实现的角度,多态性分为两类:静态多态性和动态多态性。函数重载和运算符重载实现的多态性属于静态多态性,在程序编译时系统就能决定调用的是哪个函数,因此有称为编译时的多态。静态多态性是通过函数的重载实现的(运算符重载实质上也是函数的重载)。动态多态性是在程序运行过程中才动态地确定操作所针对的对象。它又称为运行时的多态性。动态多态性是通过虚函数(virtual function)实现的。
静态多态:函数的重载和运算符的重载
动态多态:虚函数
在什么情况下应当声明虚函数
使用虚函数时,有两点注意的:
需要说明的是:使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(virtual function table,vtable),它是一个指针数组,存放每一个虚函数的入口地址。系统在进行动态关联时的时间开销是很少的,因此,多态性是高效的。
虚析构函数
情况:析构函数的作用是在对象撤销之前做必要的“清理现场”的工作。当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后再调用基类的构造函数。但是,如果用new运算符建立了临时对象,若基类中有析构函数,并且定义了一个指向该基类的指针变量。在程序用带指针参数的delete运算符撤销对象时,会发生一种情况:系统会只执行基类的析构函数,而不执行派生类的析构函数。
人们的愿望是先调用派生类的析构函数,然后再调用基类的构造函数。当基类的析构函数为虚函数时,无论指针指的是同一类族中的哪一个对象,当对象撤销时,系统会采用动态关联,调用相应的析构函数,对该对象进行清理工作。如果将基类的析构函数声明为虚函数,又该基类所派生的所有派生类的析构函数也都自动成为虚函数(即使派生类的析构函数与基类的析构函数名字不同)。
在程序中最好把积累的析构函数声明为虚函数。这将使所有的派生类自动成为虚函数。这样,如果程序中用的delete运算符准备删除一个对象,则delete运算符的操作对象是指向派生类对象的基类指针,则系统会调用相应类的析构函数。
构造函数不能声明为虚函数。这是因为在执行构造函数时类对象还未完成建立过程,当然谈不上函数与类对象的关联。
纯虚函数和抽象类
概念: 纯虚函数实在声明虚函数时被“初始化”为0的函数。一般形式为:
virtual 函数类型 函数名 (参数表列)=0;
virtual float area()const = 0;注意:
纯虚函数的作用是在基类中为其派生类保留一个函数名,以便派生类根据需要对它进行定义。如果再在基类中没有保留的函数名字,则无法实现多态性。如果在一个类中声明了一个纯虚函数,而在其派生类中没有对该函数定义,则该虚函数在派生类中仍然是纯虚函数。
抽象类
一个优秀的软件工作者在开发一个大的软件时,绝不会从头到尾都有自己编写代码,他会充分利用已有资源(例如类库)作为自己工作的基础。这种不用来定义对象而只作为一种基本类型用作继承的类,称为抽象类(abstract class),由于它常用作基类,通常称为抽象基类(abstract base class)。凡是包含纯虚函数的类都是抽象类。因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。抽象类的作用是作为一个类族的共同基类,或者说,为一个类族提供一个公共的接口。