8.2 成员函数的重载、覆盖与隐藏
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
#include <iostream.h>
class Base
{
public:
void f(int x){ cout << "Base::f(int) " << x << endl; }
void f(float x){ cout << "Base::f(float) " << x << endl; }
virtual void g(void){ cout << "Base::g(void)" << endl;}
};
class Derived : public Base
{
public:
virtual void g(void){ cout << "Derived::g(void)" << endl;}
};
void main(void)
{
Derived d;
Base *pb = &d;
pb->f(42); // Base::f(int) 42
pb->f(3.14f); // Base::f(float) 3.14
pb->g(); // Derived::g(void)
}
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆(重载的范围是在同一个类中哦))。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆(位于派生类和基类,覆盖要求必须有virtual))。
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; }
};
int _tmain(int argc, _TCHAR* argv[])
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14//不是被隐藏了吗(父类只管去调用自己的,不知道儿子的事)
pd->g(3.14f); // Derived::g(int) 3 (surprise!儿子隐藏了父类的,所以就调用自己的了)
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)//不是被隐藏了吗(父类只管去调用自己的,不知道儿子的事)
pd->h(3.14f); // Derived::h(float) 3.14(儿子隐藏了父类的,所以就调用自己的了)
}
覆盖与隐藏的区别:
在覆盖的情况下,基类调用被覆盖的函数时,直接调用子类的,自己的被盖住了。
在隐藏的情况下,基类调用被隐藏的函数时还是调用自己的,子类调用时直接调用自己的