虚函数是重载的另一种表现形式。这是一种动态的重载方式,它提供了一种更为灵活的运行时的多态性机制。虚函数允许函数调用与函数体之间的联系在运行时才建立,也就是在运行时才决定如何动作,即所谓的动态联编。
1. 虚函数的定义
虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数。虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
虚基类的定义是在基类中进行的,它是在基类中需要定义为虚函数的成员函数的声明中冠以关键字virtual。定义虚基类的方法如下:
1 | virtual 函数类型 函数名(形参表){ |
在基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新定义。在派生类中重新定义时,其函数原型,包括函数类型、函数名、参数个数、参数类型的顺序,都必须与基类中的原型完全相同。
1 | 虚函数的使用 |
说明:
(1)若在基类中,只声明虚函数原型(需加上virtual),而在类外定义虚函数时,则不必再加virtual。
(2)在派生类中,虚函数被重新定义时,其函数的原型与基类中的函数原型(即包括函数类型、函数名、参数个数、参数类型、参数类型的顺序)都必须完全相同。
(3)C++规定,当一个成员函数被定义为虚函数后,其派生类中符合重新定义虚函数要求的同名函数都自动成为虚函数。因此,在派生类中重新定义该虚函数时,关键字virtual可以写也可以不写。但是,为了使程序更加清晰,最好在每一层派生类中定义该函数时都加上关键字virtual。
(4)如果在派生类中没有对基类的虚函数重新定义,则公有派生类继承其直接基类的虚函数。一个虚函数无论继承多少次,它仍然保持其虚函数的特性。
(5)虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数,因为虚函数调用要靠特定的对象来决定该激活哪个函数。
(6)虽然使用对象名和点运算符的方式也可以调用虚函数,但是这种调用是在编译时进行的,是静态联编,它没有利用虚函数的特性。只有通过基类的指针访问虚函数时才能获得运行的多态性。
1 | 使用对象名和点运算符的方式调用虚函数。 |
2. 虚析构函数
在C++中,不能声明虚析构函数,但是可以声明虚析构函数,之前介绍过,当派生类对象撤销时,一般先调用派生类的析构函数,然后再调用基类的析构函数。