首页 理论教育C++程序设计教程:虚函数的限制

C++程序设计教程:虚函数的限制

【摘要】:内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时仍将其看作是非内联的。声明虚析构函数的目的在于:使用delete运算符删除一个对象时,能确保析构函数被正确地执行。如果不相同,则被派生类虚函数的参数类型强制转换为基类中虚函数的参数类型。

虚函数是动态绑定的基础,什么时候将一个成员函数声明为虚函数,首先要看成员函数所在的类是否为基类,然后看该成员函数在其派生类中是否需要修改功能,最后看该成员函数的调用是否需要通过基类指针或引用(形参)去访问,若满足以上三点,则将该成员函数设置为虚函数。

在设置虚函数时必须注意以下几点:

(1)只有类的成员函数才能声明为虚函数。这是因为虚函数仅适用于有继承关系的类对象,所以普通函数不能声明为虚函数。

(2)静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象。

(3)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时仍将其看作是非内联的。

(4)构造函数不能是虚函数,因为构造时对象还是一片未定型的空间。只有在构造完成后,对象才能成为一个类的名副其实的实例。

(5)析构函数可以是虚函数,而且通常声明为虚函数。声明虚析构函数的目的在于:使用delete运算符删除一个对象时,能确保析构函数被正确地执行。这是因为设置虚析构函数后,可以利用动态绑定方式选择析构函数。

(6)一般要求基类中声明了虚函数后,派生类声明的虚函数应该与基类中虚函数的参数个数相等,对应参数的类型相同。如果不相同,则被派生类虚函数的参数类型强制转换为基类中虚函数的参数类型。

【例7.4】分析以下程序的执行结果。

解:上述程序中,父类Base中的析构函数为虚函数,子类Derived中的析构函数也为虚函数。执行结果如下:

调用Derived∷~Derived()

调用Base∷~Base()

在本例程序中,如果类Base中的析构函数不用虚函数,则执行结果如下:(www.chuimin.cn)

调用Base∷~Base()

这是因为基类的析构函数声明为虚函数时,调用f(ptr)函数执行delete ptr;语句时采用动态绑定,调用它基类的析构函数,所以输出上述结果。当不将基类的析构函数声明为虚函数时,delete隐含着对析构函数的调用,也就是不调用它基类的析构函数。

【例7.5】分析以下程序的执行结果。

解:在编译上述程序时,对类Derived中的virtual void display(double b)函数给出以下警告:

warning C4244:'argument':conversion from'const double'to'int',possible loss of data(从'const double'到'int'的数据转换可能丢失数据)

在忽略警告信息后(警告信息不影响程序的运行),执行本程序出现以下结果:

Base∷display a=10

从执行结果可以看到,该虚函数的调用好像未采用动态绑定。这是因为,类Derived从类Base派生,而其中虚函数display的参数与基类中的不同,所以强制执行基类的display()函数。若将类Derived中的display()虚函数改为:

virtual void display(int a)

则执行结果如下:

Derived∷display b=10