(一)重载
成员函数被重载的条件:
- 相同的范围(在同一个类中);
- 函数名字相同;
- 参数不同;
- virtual关键字可有可无。
有关函数重载的原理可参考:c++函数重载机制实现原理
(二)覆盖(重写)
覆盖是指派生类函数覆盖其基类函数,条件如下:
- 基类指针指向派生类对象;
- 函数名字相同;
- 参数相同;
- 基类函数必须有virtual关键字;
有关函数重写(虚函数)的原理可参考:C++ 虚函数表解析
(三)隐藏(重定义)
隐藏是指派生类函数屏蔽了与其同名的基类函数,条件如下:
- 派生类指向派生类对象;
- 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意不要与重载混淆);
- 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意不要与覆盖混淆)。
示例:
#include <iostream>
using namespace std;
class Base{
public:
virtual void f(int x) { cout << "Base::f(" << x << ")" << endl; }
virtual void f(float x) { cout << "Base::f(" << x << ")" << endl; }
virtual void g() { cout << "Base::g()" << endl; }
void h(int x) { cout << "Base::h(" << x << ")" << endl; }
};
class Derived: public Base{
public:
void f(double x) { cout << "Derived::f(" << x << ")" << endl; }
void g() { cout << "Derived::g()" << endl; }
void h(int x) { cout << "Derived::h(" << x << ")" << endl; }
};
int main()
{
Base *base = new Derived();
Derived *derived = new Derived();
base->f(3); // Base::f(3)
base->f(3.14f); // Base::f(3.14) 重载
derived->f(3); // Derived::f(3) 隐藏
derived->f(3.14f); // Derived::f(3.14) 隐藏
derived->f(3.14159); // Derived::f(3.14159) 隐藏
base->g(); // Derived::g() 覆盖
derived->g(); // Derived::g()
base->h(3); // Base::h(3)
derived->h(3); // Devived::h(3) 隐藏
return 0;
}
运行结果:
Base::f(3)
Base::f(3.14)
Derived::f(3)
Derived::f(3.14)
Derived::f(3.14159)
Derived::g()
Derived::g()
Base::h(3)
Derived::h(3)
总结:
父类指针指向子类对象,只有父类的虚函数才会被子类的实现重写;
子类指针指向子类对象,先看子类实现,如果不存在或不匹配再看父类实现。