C++ 函数的重载,覆盖及隐藏
一、函数重载的解析
1、重载函数是函数的一种特殊情况,为方便使用,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。
两个重载函数必须在下列一个或两个方面有所区别:
1.)、函数有不同参数。
2.)、函数有不同参数类型,
2、重载函数被重载的特征:
1)相同的范围(在同一个类中);
2)函数名字相同;
3)参数不同;
4)virtual 关键字可有可无。
二、覆盖函数解析
1、覆盖(也叫重写)只对类的构造函数或成员函数适用,是子类继承父类是才使用的非常有用的功能。真正和多态相关。它们的地址在编译时无法确定,在运行时动态分配
2、覆盖函数的特征是:
1)不同的范围(分别位于派生类与基类);
2)函数名字相同;
3)参数相同;
4)基类函数必须有virtual 关键字。
三、函数隐藏解析
1、是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
四、函数举例
例1:举例说明函数覆盖和函数重载的关系
class Base
{
public:
void Walk(int x){ cout <<"Base::Walk(int)"<< endl; }
void Walk(float x){cout<<"Base::Walk(float)"<<endl;}
virtual void Run(void){cout<<"Base::Run(void)"<<endl;}
};
class Derived: public Base
{
public:
virtual void Run(void){cout<<"Derived::Run(void)"<<endl;}
};
// 如上关系是:Base::Walk(float)和Base::Walk(int)是函数重载关系
Derived::Run(void)覆盖了Base::Run(void),而不是虚函数重载
int main()
{
Derived der;
Base *pb = &der;
pb->Walk(20); // 调用 Base::Walk(int)
pb->Walk(1.2f); // 调用 Base::Walk(float)
pb->Run(); // 调用 Derived::Run(void)
return 0;
}
例2:举例说明函数隐藏的关系
class Base
{
public:
virtual void Walk(){ cout <<"Base::Walk()"<< endl; }
void Run(float x){cout<<"Base::Run(float)"<<endl;}
};
class Derived: public Base
{
public:
virtual void Walk(int x){ cout <<"Derived::Walk(int)"<< endl; }
void Run(int x){cout<<"Derived::Run(int)"<<endl;}
};
如上的关系是 Derived::Walk(int)隐藏了函数Base::Walk()
Derived::Run(int) 隐藏了Base::Run(float),而不是重载(不在同一个作用域内),也不是覆盖,因为函数不是虚函数
int main()
{
Derived der;
Derived* pd = &der;
pd->Run(1); // 调用Derived::Run(int)
pd->Run(1.2f); // 调用Derived::Run(int) 证明Base::Run(float)被隐藏
pd->Walk(1); // Derived::Run(int)"
// pd->Walk(); //编译无法通过,函数被隐藏
Base *pb = &der;
pb->Run(1); // 调用Base::Run(float)
pb->Run(1.2f); // 调用Base::Run(float)
pb->Walk();
//pb->Walk(1); //编译不能通过,函数被隐藏
return 0;
}