1、 虚函数的作用
允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
2、虚函数的使用方法
(1)在基类中用virtual声明成员函数为虚函数,这样可以在派生类中重新定义此函数,为它赋予新的功能,并能方便的被调用;
(2)在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体;
(3)定义一个指向基类对象的指针变量,并使它指向同一类族中的某一对象;
(4)通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。
C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。
通过虚函数与指向基类对象的指针变量的配合使用,就能方便的调用同一类族中不同类的同名函数,只要先用基类指针指向即可。如果指针不断的指向同一类族中不同类的对象,就能不断的调用这些对象中的同名函数。
需要说明: 有时在基类中定义的非虚函数在派生类中被重新定义,如果用基类指针调用该成员函数,则系统会调用对象中基类部分的成员函数;如果用派生类指针调用该成员函数,则系统会调用派生类对象中的成员函数,这并不是多态性行为(使用的是不同类型的指针),没有用到虚函数的功能。
3、 在什么情况下应当申明虚函数
使用虚函数时,有两点要注意:
(1) 只能用virtual声明类的成员函数,使它成为虚函数,而不能将类外的普通函数声明为虚函数。因为虚函数的作用是允许在派生类中对基类的虚函数重新定义。显然,它只能用于类的继承层次结构中。
(2) 一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但与该虚函数有相同参数和函数返回值类型的同名函数。
根据什么考虑是否把一个成员函数声明为虚函数呢?主要考虑一下几点:
(1) 首先看成员函数在所在类中是否会作为基类。然后看成员函数在类的继承后有无可能被更改功能,如果希望更改其功能,一般应该将它声明为虚函数;
(2) 如果成员函数在类被继承后功能不需要修改,或派生类中用不到该函数,则不要把它声明为虚函数。不要仅仅考虑要作为基类而把类中的所有成员函数都设为虚函数。
(3) 应考虑对成员函数的调用是通过对象名还是通过基类指针或引用去访问它,如果是通过基类指针或引用去访问的,则应当声明为虚函数。
(4) 有时,在定义虚函数时,并不定义函数体,即函数体是空的,它的作用只是定义了一个虚函数名,具体功能留给派生类去添加。
需要说明:使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(virtual function table,简称vtable),它是一个指针数组,存放每个虚函数的入口地址。系统在进行动态关联时的时间开销是很小的,因此,多态性是高效的。
4、 虚析构函数的讨论
析构函数的作用是在对象撤销之前做必要的清理现场的工作。当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后再调用基类的析构函数。但是,如果用new运算符建立了临时对象,若基类中有析构函数,并且定义了一个指向该基类的指针变量。在程序用带指针参数的delete运算符撤销对象时,会发生一个情况:系统只会执行基类的析构函数,而不执行派生类的析构函数。
最好把基类的析构函数声明为虚函数,这将使所有派生类的析构函数自动成为虚函数。这样,如果程序中使用delete运算符准备删除一个对象,而delete运算符的操作对象是指向派生类对象的基类指针,则系统会调用相应类的析构函数。
5、 构造函数不能申明为虚函数
因为在执行构造函数时,类对象还未完成建立过程,当然谈不上函数与类对象的关联。