引例
class employee {
public:
void salary ( ) {
}
} ;
class manager : public employee {
public:
void salary ( ) {
}
} ;
class programmer : public employee {
public:
void salary ( ) {
}
} ;
void payroll ( employee& re) {
re. salary ( ) ;
} ;
payroll()是面向基类进行处理的函数,具有一般性,能够处理任意的employee对象,还有很好的可拓展性。如果想要加上新员工种类,只要再定义一个employee的派生类,不用修改payroll()。
但是本例中假如定义了一个manager对象Jerry,输入payroll(Jerry),编译器只能知道Jerry是employee而不知道是manager。所以调用的是employee中的salary函数,而不是manager中的salary函数。
将函数体和函数调用相联系称为绑定 ,默认的函数调用绑定方式是静态绑定 ,又称为早绑定 。解决上述问题的方法是使用动态绑定 ,将绑定推迟到程序运行时,以便根据具体类型绑定函数调用。动态绑定又称晚绑定 或运行时绑定 。
利用动态绑定能实现多态性——同样的消息发送给不同的派生类的对象时执行不同的操作。在C++中,为提高效率,只对虚函数实施动态绑定。
虚函数
为了对成员函数进行动态绑定,要在基类中将该成员函数声明为虚函数。虚函数声明语法是在成员函数前加关键字“virtual”
只有非静态成员函数可以声明为虚函数
在派生类中覆盖基类虚函数时要用相同的参数表和返回类型,否则:
若参数表不同,被视为定义了另一个同名函数,在派生类中隐藏基类虚函数,不能再进行多态调用。
若返回值类型不同,会报错。
构造函数不能是虚函数,析构函数可以是虚函数,基类的析构函数如果声明为虚函数,其派生类析构函数即使不加virtual 也是虚函数。(析构函数最好声明为虚函数)
使用虚函数实现多态性的步骤:
在基类中将需要多态调用的成员函数声明为virtual
在派生类中覆盖基类的虚函数,实现各自需要的功能
用基类的指针或引用 指向派生类对象 ,调用虚函数。通过对象调用虚函数不会有多态性 。
基类指针(引用)即使在指向派生类对象时,也只能调用基类接口中出现的成员函数,不能调用派生类中增加的成员函数。
实例
#include <iostream>
using namespace std;
class Base {
public:
virtual void