重载:函数被重载是发生在同一个范围内的,例如一个类中的两个成员函数,函数名相同,但是参数不同,与virtual关键字无关系。
class A
{
void f();//3个f互为重载函数
void f(int);
void f(int,float);
}
覆盖:函数覆盖发生在不同的范围类,例如位于派生类与基类中的两个函数,函数名相同,参数也相同,而且基类函数必须要有virtual关键字修饰,这也是实现多态的基础。
下面的例子是Base类的f(),被派生类Derived的f()所覆盖了,因此p->调用的是Derived的f(),此时Derived类的虚函数表中的父类虚函数被子类的函数所覆盖。
class Base
{
public:
virtual void f(void){cout<<"Base::f(void)"<<endl;}
}
class Derived : public Base
{
public:
void f(void){cout<<"Derived::f(void)"<<endl;}
};
void main()
{
Base *p = new Derived;
p->f();//Derived::f(void)
}
隐藏:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
如下例所示,bp 和dp 指向同一地址,按理说运行结果应该是相同的,可是事实并非这样。实际编程中,应该注意,避免隐藏。
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
};
class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};
void main()
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
pb->f(3.14f); // Derived::f(float) 3.14 覆盖
pd->f(3.14f); // Derived::f(float) 3.14
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3 (surprise!)
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
pd->h(3.14f); // Derived::h(float) 3.14
}