目錄
- 1、繼承中的名字隱藏
- 1.基類同名函數被隱藏的現象描述
- 2.問題理解
- 3.避免現象
- 2、重定義
- 1.現象描述
- 2.重定義與重載的區別
- 3.能否使用 using 將基類成員引入到派生類定義中
1、繼承中的名字隱藏
1.基類同名函數被隱藏的現象描述
在學習變量作用域的時候知道,全局變量可能被函數里面的同名局部變量所隱藏,如果要在函數里面使用這個同名全局變量,那么就要使用域解析運算符。
在繼承中也會出現上述類似的情況,下面是名字隱藏的形式:
基類和派生類中都有一個同名函數,不同的是派生類的函數有個整型形參。
在主函數中調用f(),那么調用的到底是基類的函數還是派生類的函數?
class P{public:void f(){}
};class C :public P{public:void f(int x){}
};
int main()
{C c;c.f();
}
編譯器會報錯。
2.問題理解
我們可以將派生類看做是內部作用域,基類看做是外部作用域。內部作用域的函數f()將外部作用域的f()給隱藏掉了。
那么在C類中就看不到基類中的f()同名函數了。
這個做法可以幫助程序員避免寫出帶有危險性的代碼。
3.避免現象
那么如何解決這個問題呢?
using 聲明語句可以將基類成員引入到派生類定義中,顯式聲明。
class P{public:void f(){}
};class C :public P{public:using P::f;void f(int x){}
};
int main()
{C c;c.f();
}
其實還有兩種寫法:
1、
class P{public:void f(){}
};class C :public P{public:void f(int x){}
};
int main()
{C c;c.P::f();
}
2、
class P{public:void f(){}
};class C :public P{public:void f(int x){}
};
int main()
{C c;static_cast<P>(c).f();
}
2、重定義
1.現象描述
名字隱藏在重定義函數的時候有比較大的作用。因為有名字隱藏,所以我們可以在子類里面重新定義一個與基類里面名字參數一樣的函數
。
之前定義了基類shape:
其中,toString函數用來描述對象的信息。基類可以調用這個函數,但是基類是無法輸出派生類信息的。
例如形狀就不能輸出它的派生類:圓,的半徑。只能輸出顏色和是否填充。
我們可以在派生類里面重新定義toString函數用來描述派生類對象,這樣就不會調用基類的toString函數了。
2.重定義與重載的區別
重載
多個函數名字相同,但至少以下一個特征不同:
1、參數類型(parameter type)
2、參數數量(parameter number)
3、參數順序(parameter sequence)
重定義
1、函數特征相同:同名、同參數、返回值類型
2、在基類和派生類中都有定義
3.能否使用 using 將基類成員引入到派生類定義中
派生類B中的 foo()函數是對基類A中的 foo() 函數的重定義。
那么在類B中,能否使用 using 講基類A中的foo()函數引入到派生類B中?為什么?
#include<iostream>#include<string>using namespace std; class A {public: string func() { return "aaa"; }};class B :public A {public:using A::func; string func() { return "bbb"; }}; int main() { A a; B b; cout<<a.func()<<endl;cout<<b.func()<<endl; }結果是:aaabbb編譯運行正常通過,所以還是調用了 子類 的函數。