只要基类在定义成员函数时已经声明了virtual关键字,在派生类实现的时候覆盖该函数时,virtual关键字可加可不加,不影响多态的实现。
容易与隐藏混淆:
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
1) 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
2) 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意这种情况与函数重载的区别,重载发生在同一个类中。)。
#include<iostream>
using namespace std;
class Base
{
public:
virtual void f(float x)
{
cout<<"BASE::f"<<x;
}
virtual void g(float x)
{
cout<<"BASE::g"<<x;
}
void h(float x)
{
cout<<"BASE::h"<<x;
}
};
class Driver:public Base
{
public:
void f(float x)
{
cout<<"d::f"<<x;
}
virtual void g(int x)
{
cout<<"d::g"<<x;
}
void h(float x)
{
cout<<"d::h"<<x;
}
};
int main(int argc, char const *argv[])
{
Driver d;
Base* pb=&d;
Driver* pd=&d;
pd->f(1.2f);
pb->f(1.2f);
pd->g(1.2f);
pb->g(1.2f);
pd->h(1.2f);
pb->h(1.2f);
return 0;
}
请大家注意,f()函数属于覆盖,而g()与h()属于隐藏。从上面的运行结果,我们可以注意到在覆盖中,用基类指针和派生类指针调用函数f()时,系统都是执行的派生类函数f(),而非基类的f()。而在隐藏方式中,用基类指针和派生类指针调用函数g()、h()时,系统会进行区分,基类指针调用时,系统执行基类的g()、h(),而派生类指针调用时,系统“隐藏”了基类的f(),执行派生类的f(),这也就是“隐藏”的由来。