成员函数的重载,覆盖,和隐藏很容易混淆
成员函数的重载:
1. 必须在同一作用域内
2. 函数名字相同
3. 参数列表不同(包括参数个数, 参数类型或者顺序不同)
不受virtual的影响
成员函数的覆盖:
1. 为别位于基类和派生类中
2. 函数名相同
3. 参数列表完全相同
4. 基类函数必须有virtual修饰(virtual关键字告诉编译器,派生类中相同的函数应放到vtable中,并替换相应函数的槽位)
#include <iostream>
using namespace std;
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(float) "<<endl;}
};
class Derive: public Base
{
public:
void g(void){cout<<"Derive::g(void) "<<endl;}
};
int main()
{
Derive d;
Base* pb = &d;
pb->f(1);
pb->f(1.23f);
pb->g();
return 0;
}
f构成了重载,会根据不同的实参调用不同的函数,pb指针运行时绑定,不同的对象的pb指向派生类的对象调用
派生类的函数。
成员函数的隐藏规则:
1. 派生类的函数与基类的函数同名,但是参数列表有所差异。 此时不论有没有virtual关键字,基类的函数在派
生类中都将被隐藏。
2. 派生类的函数与基类的函数同名,参数列表也相同,但是基类函数没有virtual关键字。基类的函数也会被隐藏。
#include <iostream>
using namespace std;
class Base{
public:
void f(float x){cout<<"Base::f(double) "<<x<<endl;}
void g(float x){cout<<"Base::g(float) "<<x<<endl;}
virtual void h(void){cout<<"Base::h(void) "<<endl;}
};
class Derive: public Base
{
public:
void f(float x){cout<<"Derive::f(float) "<<x<<endl;}
void g(int x){cout<<"Derive::g(int) "<<x<<endl;}
virtual void h(void){cout<<"Derive::h(void) "<<endl;}
};
int main()
{
Derive d;
Base* pb = &d;
Derive* pd = &d;
pb->f(1.23f);
pd->f(1.23f);
pb->g(1.23f);
pd->g(1.23f);
pb->h();
pd->h();
return 0;
}