一.序言
前面一篇區分了重載/覆寫/隐藏,那麼這一篇先給一個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();//Der::f_float,覆寫
pd->f();//Der::f_float,正常
cout<<"--------------->"<<endl;
pb->g();//Base::g_float,這就是隐藏與覆寫的差別,如果是覆寫的情況的話,列印出來的應是Der::g_int.由于是父類指針調用父類的g函數,隐藏隻是子類的方法隐藏父類,當子類調用時,不受父類同名方法的影響;
pd->g();//Der::g_int,隐藏
cout<<"--------------->"<<endl;
pb->h();//Base::h_float,同pb->g(3.14f)情況
pd->h();//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();//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);}
};