一.序言
前面一篇区分了重载/覆盖/隐藏,那么这一篇先给一个magic的例子。
class Base
{
public:
virtual void f(float a){cout<<"Base::f_float"<<endl;}
void g(float a){cout<<"Base::g_float"<<endl;}
void h(float x){cout<<"Base::h_float"<<endl;}
};
class Der : public Base
{
public:
void f(float a){cout<<"Der::f_float"<<endl;}
void g(int a){cout<<"Der::g_int"<<endl;}
void h(float a){cout<<"Der::h_float"<<endl;}
};
int main()
{
Der d;
Base *pb = &d;
Der *pd = &d;
pb->f(3.14f);//Der::f_float,覆盖
pd->f(3.14f);//Der::f_float,正常
cout<<"--------------->"<<endl;
pb->g(3.14f);//Base::g_float,这就是隐藏与覆盖的区别,如果是覆盖的情况的话,打印出来的应是Der::g_int.由于是父类指针调用父类的g函数,隐藏只是子类的方法隐藏父类,当子类调用时,不受父类同名方法的影响;
pd->g(3.14f);//Der::g_int,隐藏
cout<<"--------------->"<<endl;
pb->h(3.14f);//Base::h_float,同pb->g(3.14f)情况
pd->h(3.14f);//Der::h_float,隐藏
}
先看结果
每种情况的分析请见代码
二.隐藏规则存在的意义
class Base
{
public:
void f(int x){cout<<"Base::f_int"<<endl;};
};
class Der : public Base
{
public:
void f(char *str){cout<<"Der::f_char*"<<endl;}
};
int main()
{
Der d;
d.f(10);//error,从类型‘int’到类型‘char*’的转换无效
}
也许你的本义是想调用函数Base::f(int a),但是它被隐藏掉了。由于整型10不能隐式的转化成char*类型,所以编译时报错。
但是你不能因为这就说C++的隐藏特性没有用。给出理由:
(1)也许我本来就是想调用Der::f(char *str);恰好因为C++的隐藏规则指出了我的错误。
(2)如果Der类继承了多个父类(多重继承),最后谁也不知道哪个父类里定义了f函数,如果没有隐藏规则,会很莫名其妙的调用某个f函数。隐藏可以避免这些意外的发生
如果一定要调用Base::f(int),可以这样修改代码
class Der : public Base
{
public:
void f(char *str){cout<<"Der::f_char*"<<endl;}
void f(int a){Base::f(a);}
};