这里讲重载(overload)、覆盖(override)、隐藏是基于OOP的继承、多态来阐述。 三者有一点是完全相同的,那就是讨论的函数都是同名的。
1、重载比较好理解,是指与许存在多个同名函数,而这些函数的参数表不同(或者参数个数不同、或者参数类型不同、或者两者皆不同)。注意:仅仅是函数的返回值不同的重载,编译器是会嗷嗷叫的!
类成员函数被重载的特征:
- 相同的范围(在同一个类中);
- 函数名字相同;
- 参数不同(或者参数个数不同、或者参数类型不同、或者两者皆不同);
- virtual 关键字可有可无。
这里要偏离下主题,备案一个刚刚获知的知识点。一直以来,我以为复制构造函数有以下两种重载原型:
Myclass(Myclass &);
Myclass(const Myclass &);
今天又学一手,还有第三种复制构造函数原型:
Myclass(volatile Myclass &);
2、言归正传,而覆盖是指派生类函数覆盖基类函数,它总是和继承、多态扯上千丝万缕的关系,可谓你中有我,我中有你
!它的特征如下:
- 不同的范围(分别位于派生类与基类);
- 函数名字相同;
- 参数相同(vs2005里两个函数的返回值也要一样,否则报error);
- 基类函数必须有virtual 关键字。
也就是说分别处于互为继承关系的类中,两个完全相同的一模一样的虚函数才有覆盖的概念!
看如下代码:
#include <iostream>
using namespace std;
class base
{
public:
void f(int x) { cout<< “base::f(int)” << endl; }
void f(float y) { cout << “base::f(float)” << endl;}
virtual void g(void) { cout << “base::g(void)” << endl; }
};
class derived:public base
{
public:
//这里的virtual可要可不要,因为基类函数有virtual,继承类同名同参数函数自动加上virtual
virtual void g(void) { cout << “derived::g(void)” << endl;}
};
int main()
{
derived d;
base * pb=&d;
pb->f(10); //base::f(int)
pb->f(3.1415f); //base::f(float)
pb->g(); //derived::g(void)
}
base类中void f(int x)和void f(float y)就属于重载,而derived::g(void)就是覆盖base::g(void)。
3、前面两者还算好区分,C++里的隐藏才是令人迷惑。隐藏指派生类的函数屏蔽了与其同名的基类函数,其规则如下:
- 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
- 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
这两句话可以这么理解:通过继承类对象、指针或者引用没有办法调用到基类中的那个函数,这叫继承类隐藏了基类的函数;反之亦然!也就是说隐藏在继承层次中是相互的,你隐藏我,我也隐藏你!
一句话概括:如果两个函数分别在继承关系的类中,只要不是覆盖关系,那么一定就是屏蔽关系!!
将上述两个类代码换成如下形式:
class base
{
public:
void f(int x) { cout<< “base::f(int)” << endl; }
void g(void) { cout << “base::g(void)” << endl; }
};
class derived:public base
{
public:
void f(float y) { cout << “base::f(float)” << endl;}
void g(void) { cout << “derived::g(void)” << endl;}
};
这里derived::f(float y)就是第一种方式隐藏base::f(int x);derived::g(void)就是第二种方式隐藏base::g(void)