學習過C++基礎課程的人,對重載函數的概念相對熟悉一些,但是對覆蓋和隱藏就相對陌生了,在編程技術的學習上,你會發現一個規律,很多知識點你都知道,但是一旦用起來,就常常出錯,為什么呢?筆者一直都在探索這個問題。。
重載函數有哪些特性呢?
《高質量C++/C編程指南》已經清晰的列出了重載函數的特性:
(1)相同的范圍(在同一個類中); (2)函數名字相同; (3)參數不同; (4)virtual關鍵字可有可無。
因為函數參數不同,可以簡單的理解為:兩個重載函數是不同的函數,調用者能夠明確的根據不同的參數來調用不同的函數。那么如果存在這樣兩個函數,編譯器怎么處理呢?
class A{public: void Func(int a, int b=0) {PRintf("This is Func1/n");} void Func(int a) {printf("This is Func2/n");}};
int main(){ A a; a.Func(5); return 0;}
當然,對于這樣兩個函數,調用者不知道應該調用哪個函數,故編譯器直接報錯。
我們在看看,覆蓋和隱藏分別是什么特性呢?從字面意思來講,覆蓋和隱藏都具有一個把另一個給遮住了,那只不過是誰遮誰的問題。
覆蓋:是指派生類函數覆蓋基類函數,只作用于派生類函數,其特性為:(1)不同的范圍(分別位于派生類與基類);(2)函數名字相同;(3)參數相同;(4)基類函數必須有virtual關鍵字。
我們發現,這里用到了虛函數,實際上虛函數的作用,就是實現覆蓋。
隱藏:是指派生累函數將基類函數給藏起來了,當然只作用于派生類函數,其特性與覆
蓋不同。(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏。
(2)如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏。
這里的隱藏和覆蓋的含義,感覺上非常的模糊,甚至不清,并且隱藏的規則,常常令人感覺到神出鬼沒。。。
請參看如下實例:
class Base{public: virtual void f(float x){ cout << "Base::f(float) " << x << endl; } void g(float x){ cout << "Base::g(float) " << x << endl; } void h(float x){ cout << "Base::h(float) " << x << endl; }};
class Derived : public Base{public: virtual void f(float x){ cout << "Derived::f(float) " << x << endl; } void g(int x){ cout << "Derived::g(int) " << x << endl; } void h(float x){ cout << "Derived::h(float) " << x << endl; }};
void main(void){ Derived d; Base *pb = &d; Derived *pd = &d; pb->f(3.14f); pd->f(3.14f); // Bad : behavior depends on type of the pointer pb->g(3.14f); pd->g(3.14f); // Bad : behavior depends on type of the pointer pb->h(3.14f); pd->h(3.14f); }
令人非常不解,bp和dp指向同一地址,按理說運行結果應該是相同的,可事實并非這樣。所以我們還是要想辦法擺脫隱藏。
還有一點要切忌,對于static這種靜態成員函數,是屬于類的方法,而不是對象的方法,所以static方法絕對不能被覆蓋或者隱藏。
轉自:http://blog.csdn.net/hexi_2000/article/details/4392107
新聞熱點
疑難解答