程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 探索C++的秘密之二:重載,覆蓋,和隱藏

探索C++的秘密之二:重載,覆蓋,和隱藏

編輯:關於C語言
 

這幾個概念都有一個共同點:函數名稱相同,所以不免讓人混淆,大致的區別如下:

重載(overload):
必須在一個域中,函數名稱相同但是函數參數不同,重載的作用就是同一個函數有不同的行為,因此不是在一個域中的函數是無法構成重載的,這個是重載的重要特征

覆蓋(override):
覆蓋指的是派生類的虛擬函數覆蓋了基類的同名且參數相同的函數,既然是和虛擬函數掛鉤,說明了這個是一個多態支持的特性,所謂的覆蓋指的是用基類對象的指針或者引用時訪問虛擬函數的時候會根據實際的類型決定所調用的函數,因此此時派生類的成員函數可以"覆蓋"掉基類的成員函數.
注意唯有同名且參數相同還有帶有virtual關鍵字並且分別在派生類和基類的函數才能構成虛擬函數,這個也是派生類的重要特征.
而且,由於是和多態掛鉤的,所以只有在使用類對象指針或者引用的時候才能使用上.
總之一句話:覆蓋函數都是虛函數,反之不然~~

隱藏(hide):
指的是派生類的成員函數隱藏了基類函數的成員函數.隱藏一詞可以這麼理解:在調用一個類的成員函數的時候,編譯器會沿著類的繼承鏈逐級的向上查找函數的定義,如果找到了那麼就停止查找了,所以如果一個派生類和一個基類都有同一個同名(暫且不論參數是否相同)的函數,而編譯器最終選擇了在派生類中的函數,那麼我們就說這個派生類的成員函數"隱藏"了基類的成員函數,也就是說它阻止了編譯器繼續向上查找函數的定義....
回到隱藏的定義中,前面已經說了有virtual關鍵字並且分別位於派生類和基類的同名,同參數函數構成覆蓋的關系,因此隱藏的關系只有如下的可能:
1)必須分別位於派生類和基類中
2)必須同名
3)參數不同的時候本身已經不構成覆蓋關系了,所以此時是否是virtual函數已經不重要了
當參數相同的時候就要看時候有virtual關鍵字了,有的話就是覆蓋關系,沒有的時候就是隱藏關系了

上面的解說大體把三者的區別給說清楚了,但是還有一些疑惑的地方,以下以代碼例子說明.

很多人分辨不清隱藏和覆蓋的區別,因為他們都是發生在基類和派生類之中的.但是它們之間最為重要的區別就是:
覆蓋的函數是多態的,是存在於vtbl之中的函數才能構成"覆蓋"的關系,而隱藏的函數都是一般的函數,不支持多態,在編譯階段就已經確定下來了.


class Base
{
public :
virtual void f( float x) {cout << " Base::f(folat) " << x << endl;}
void g( float x) {cout << " Base::g(float) " << x << endl;}
} ;

class Derived: public Base
{
public :
virtual void f( float x) {cout << " Derived::f(float) " << x << endl;}
void g( int x) {cout << " Deriver::g(int) " << x << endl;}
} ;

int main()
{
Derived d;
Base * pb =& d;
Derived * pd =& d;
pb -> f( 3.14f );
pd -> f( 3.14f );
pb -> g( 3.14f ); // 輸出結果:Base::g(float)3.14
pd -> g( 3.14f ); // 輸出結果:Dervied::g(int)3
return 0 ;
}

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved