虚函数的定义要遵循以下重要规则:
1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后联编的。
2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。
5.构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。
6.析构函数可以是虚函数,而且通常声名为虚函数。
说明一下,虽然我们说使用虚函数会降低效率,但是在处理器速度越来越快的今天,将一个类中的所有成员函数都定义成为virtual总是有好处的,它除了会增加一些额外的开销是没有其它坏处的,对于保证类的封装特性是有好处的。 对于上面虚函数使用的重要规则6,我们有必要用实例说明一下,为什么具备多态特性的类的析构函数,有必要声明为virtual。
代码如下: #include <iostream> using namespace std; class Vehicle { public: Vehicle(float speed,int total) { Vehicle::speed=speed; Vehicle::total=total; } virtual void ShowMember() { cout<<speed<<"|"<<total<<endl; } virtual ~Vehicle() { cout<<"载入Vehicle基类析构函数"<<endl; cin.get(); } protected: float speed; int total; }; class Car:public Vehicle { public: Car(int aird,float speed,int total):Vehicle(speed,total) { Car::aird=aird; } virtual void ShowMember() { cout<<speed<<"|"<<total<<"|"<<aird<<endl; } virtual ~Car() { cout<<"载入Car派生类析构函数"<<endl; cin.get(); } protected: int aird; }; void test(Vehicle &temp) { temp.ShowMember(); } void DelPN(Vehicle *temp) { delete temp; } void main() { Car *a=new Car(100,1,1); a->ShowMember(); DelPN(a); cin.get(); } 从上例代码的运行结果来看,当调用DelPN(a);后,在析构的时候,系统成功的确定了先调用Car类的析构函数,而如果将析构函数的virtual修饰去掉,再观察结果,会发现析构的时候,始终只调用了基类的析构函数,由此我们发现,多态的特性的virtual修饰,不单单对基类和派生类的普通成员函数有必要,而且对于基类和派生类的析构函数同样重要。
|