C++的重载(overload)与重写(override)
C++的重載(overload)與重寫(override)
成員函數(shù)被重載的特征:
(1)相同的范圍(在同一個類中);
(2)函數(shù)名字相同;
(3)參數(shù)不同;
(4)virtual關(guān)鍵字可有可無。
重寫是指派生類函數(shù)重寫基類函數(shù),是C++的多態(tài)的表現(xiàn),特征是:
(1)不同的范圍(分別位于派生類與基類);
(2)函數(shù)名字相同;
(3)參數(shù)相同;
(4)基類函數(shù)必須有virtual關(guān)鍵字。
示例中,函數(shù)Base::f(int)與Base::f(float)相互重載,而Base::g(void)被Derived::g(void)重寫。
#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(void)" << endl;} };class Derived : public Base { public:virtual void g(void){ cout << "Derived::g(void)" << endl;} };int main() {Derived d;Base *pb = &d;pb->f(42); // Base::f(int) 42pb->f(3.14f); // Base::f(float) 3.14pb->g(); // Derived::g(void)return 0; }令人迷惑的隱藏規(guī)則
本來僅僅區(qū)別重載與重寫并不算困難,但是C++的隱藏規(guī)則(遮蔽現(xiàn)象)使問題復雜性陡然增加。這里“隱藏”是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù),規(guī)則如下:
(1)如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同。此時,不論有無virtual關(guān)鍵字,基類的函數(shù)將被隱藏。
(2)如果派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有virtual關(guān)鍵字。此時,基類的函數(shù)被隱藏。
這種隱藏規(guī)則,不僅僅是表現(xiàn)在對成員函數(shù)上,對同名的data member也是如此。
示例程序中:
(1)函數(shù)Derived::f(float)重寫了Base::f(float)。
(2)函數(shù)Derived::g(int)隱藏了Base::g(float)。
(3)函數(shù)Derived::h(float)隱藏了Base::h(float)。
另一個關(guān)于虛函數(shù)很微妙的錯誤情況:參數(shù)相同,但是基類的函數(shù)是const的,派生類的函數(shù)卻不是。
#include <iostream> using namespace std;class Base { public:virtual void f(float x){ cout << "Base::f(float) " << x << endl; } };class Derived : public Base { public:virtual void f(float x) const { cout << "Derived::f(float) " << x << endl; } };int main() {Derived d;Base *pb = &d;Derived *pd = &d;// Bad : behavior depends solely on type of the objectpb->f(3.14f); // Base::f(float) 3.14pd->f(3.14f); // Derived::f(float) 3.14return 0; }(1)一個函數(shù)在基類申明一個virtual,那么在所有的派生類都是是virtual的。
(2)一個函數(shù)在基類為普通函數(shù),在派生類定義為virtual的函數(shù)稱為越位,函數(shù)行為依賴于指針/引用的類型,而不是實際對象的類型。
《Effective C++》條款: 決不要重新定義繼承而來的非虛函數(shù)。說明了不能重新定義繼承而來的非虛函數(shù)的理論依據(jù)是什么。
以下摘自《Effective C++》:
公有繼承的含義是 "是一個","在一個類中聲明一個非虛函數(shù)實際上為這個類建立了一種特殊性上的不變性"。如果將這些分析套用到類B、類D和非虛成員函數(shù)B::mf,那么:
(1)適用于B對象的一切也適用于D對象,因為每個D的對象 "是一個" B的對象。
(2)B的子類必須同時繼承mf的接口和實現(xiàn),因為mf在B中是非虛函數(shù)。
那么,如果D重新定義了mf,設(shè)計中就會產(chǎn)生矛盾。如果D真的需要實現(xiàn)和B不同的mf,而且每個B的對象(無論怎么特殊)也真的要使用B實現(xiàn)的mf,那么每個D將不 "是一個" B。這種情況下,D不能從B公有繼承。相反,如果D真的必須從B公有繼承,而且D真的需要和B不同的mf的實現(xiàn),那么,mf就沒有為B反映出特殊性上的不變性。這種情況下,mf應(yīng)該是虛函數(shù)。最后,如果每個D真的 "是一個" B,并且如果mf真的為B建立了特殊性上的不變性,那么,D實際上就不需要重新定義mf,也就決不能這樣做。
不管采用上面的哪一種論據(jù)都可以得出這樣的結(jié)論:任何條件下都要禁止重新定義繼承而來的非虛函數(shù)。
? ? 本文轉(zhuǎn)自阿凡盧博客園博客,原文鏈接:http://www.cnblogs.com/luxiaoxun/archive/2012/08/09/2630751.html,如需轉(zhuǎn)載請自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的C++的重载(overload)与重写(override)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正版软件 - AxMath 专业的数学公
- 下一篇: 智能车基础学习FTM模块