C 過載 覆蓋和隱藏

2021-06-27 22:47:00 字數 3195 閱讀 8134

過載、覆蓋和隱藏

共同點:函式名稱相同。

(1)過載:必須在乙個域內,函式名稱相同但是函式引數不同。過載的作用就是同乙個函式有不同的行為。

過載完全是乙個編譯時(或靜態)的概念。如果宣告了同名函式,編譯器會在編譯時處理這些同名函式的呼叫問題,

確定呼叫哪乙個函式,執行時不 涉及呼叫過載函式的額外開銷或決定。而且,過載只用於函式,不用於類。

函式過載的特徵:(1)相同的範圍(在同乙個類中);(2)函式名稱相同;(3)引數不同;(4)virtual關鍵字可有可無

分析:因為函式引數不同,可以簡單的理解為:兩個過載函式是不同的函式,呼叫者能夠明確的根據不同的引數來呼叫不同的函式。

那麼如果存在這樣兩個函式,編譯器怎麼處理呢?

例子:class a

void func(int a)

};int main()

當然,對於這樣兩個函式,呼叫者不知道應該呼叫哪個函式,故編譯器直接報錯。

(2)覆蓋:也稱為重新定義(redefinition)。派生類希望覆蓋所繼承的行為,使得派生類的物件表現出自身的行為而非基類物件的行為。

覆蓋的特性:(1)不同的範圍(函式分別位於派生類與基類);(2)函式名字相同;(3)引數相同;(4)基類函式必須有virtual

關鍵字。

我們發現,這裡用到了虛函式,實際上虛函式的作用,就是實現覆蓋。

分析:既然和虛函式掛鉤,說明了這個是多型支援的特性(通過基類指標或引用間接指向派生類子型別時才有效)。

只有在基類中宣告為virtual的成員函式才能在派生類中被覆蓋,不可能覆蓋在基類中未宣告為virtual的函式。但是,僅在基類

的某函式前加virtual關鍵之,派生類不能據此將其解釋為允許覆蓋該函式,基類的設計者應該將可覆蓋的函式宣告為虛函式,

並在文件中明確陳述派生類可覆蓋該函式。總之一句話,覆蓋函式都是虛函式,反之,不然。

覆蓋是執行時的概念,它在執行時從一組被覆蓋的函式中選擇乙個函式。只有動態繫結才能使用覆蓋機制。通過覆蓋,使

用的是物件所實現的正確的方法,而不是呼叫介面所使用的方法。覆蓋基於單個函式,派生類的方法覆蓋在基類中宣告的同名

方法,覆蓋只應用於類中的方法,不能應用於自由函式。覆蓋意味著繼承關係,沒有繼承,就不存在覆蓋。

例子:class base  

void f(float x)

virtual void g(void)

};class derived : public base  

};void main(void)

函式base::f(int)與base::f(float)相互過載,而base::g(void)被derived::g(void)覆蓋。

(3)隱藏:指的是派生類的成員函式隱藏了基類函式的成員函式。隱藏的意思是,雖然現在看不到,但是並不表明不存在,只是暫時被隱

藏起來了而已,所以,如果將乙個子類的物件賦值給乙個基類的指標,那麼用該指標呼叫對應的成員函式時,呼叫的是被派生

類隱藏了的對應的基類的成員函式。

隱藏的規則:

(1)如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏。

(注意別與過載混淆)

(2)如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏。

(注意別與覆蓋混淆)

分析:隱藏一詞可以這麼理解:在呼叫乙個類的成員函式的時候,編譯器會沿著類的繼承鏈逐級的向上查詢函式的定義,如果

找到了那麼就停止查詢了,所以如果乙個派生類和乙個基類都有同乙個同名(暫且不論引數是否相同)的函式,而編譯器

最終選擇了在派生類中的函式,那麼我們就說這個派生類的成員函式"隱藏"了基類的成員函式,也就是說它阻止了編譯

器繼續向上查詢函式的定義。

例子(1):

class base

virtual void g(float x)

void h(float x)

};class derived : public base

virtual void g(int x)

void h(float x)

};在這個例子(1)中,(a)函式derived::f(float)覆蓋了base::f(float)。

(b)函式derived::g(int)隱藏了base::g(float),而不是過載。

(c)函式derived::h(float)隱藏了base::h(float),而不是覆蓋。

總結:過載與隱藏:相同點:(1)函式名相同(2)引數都不同(3)virtual關鍵字可有可無。

過載的函式,virtual關鍵字可有可無。

不同點:(1)範圍不同。過載的函式在同乙個範圍內(同乙個類),隱藏的函式在基類和派生類。

覆蓋與隱藏:相同點:(1)範圍相同:函式在基類和派生類(2)函式名相同(3)引數相同

不同點:(1)virtual關鍵字。基類如果沒有virtual關鍵字,則被隱藏。而覆蓋,基類必須有virtual關鍵字。

即,覆蓋的函式是多型的,是存在於vtbl之中的函式才能構成「覆蓋」關係,而隱藏的函式

都是一般的函式,不支援多型,在編譯階段就已經確定下來了。

例子(2):

void main(void)

在例子(2)中,令人非常不解,bp和dp指向同一位址,按理說執行結果應該是相同的,可事實並非這樣。所以我們還是要

想辦法擺脫隱藏。

分析:出現surprise!的地方,還是和函式的動、靜態繫結有關係。f函式是虛函式,但是h函式不是。宣告為虛函式的類裡面,

都包含乙個vptr指標和乙個所謂的虛函式表(vtbl)。在程式編譯的時候,函式指標(指向函式的指標變數)f、g、h就已

經是確定的了,但是vptr指標根據不同的偏移量而不同,且這個變化是在執行期動態決定的。也就是說,函式的位址不

可變,但是vptr可變。**base *pb = &d;只是用derived類物件d的vptr修改了base類pb的vptr指標,但是當base

類成員建立的時候,f,g,h函式指標是不能改變的。

當函式宣告為virtual的時候,就啟用了多型機制,程式在執行的時候會根據型別的實際型別到vtbl中查詢函式指標,

去呼叫正確的函式來執行。h函式指標的型別在編譯的時候已經確認了,所以在程式執行的時候不能發生改變,從而發生

了在子類中的「隱藏」現象。

注意:還有一點要切忌,對於static這種靜態成員函式,是屬於類的方法,而不是物件的方法,

所以static方法絕對不能被覆蓋或者隱藏。

C 過載 覆蓋 和隱藏

這幾個概念都有乙個共同點 函式名稱相同,所以不免讓人混淆,大致的區別如下 過載 overload 必須在乙個域中,函式名稱相同但是函式引數不同,過載的作用就是同乙個函式有不同的行為,因此不是在乙個域中的函式是無法構成過載的,這個是過載的重要特徵 覆蓋 override 覆蓋指的是派生類的虛函式覆蓋了...

c 過載 覆蓋和隱藏

成員函式過載的特徵 1 相同的範圍 在同乙個類中 2 函式名字相同 3 引數不同 4 virtual關鍵字可有可無 函式覆蓋指的是派生類函式覆蓋基類函式,1 要求不同的範圍 分別位於派生類與基類中 2 函式名字要求相同 3 引數要求相同 4 基類和拿書必須有virtual關鍵字 隱藏是指派生類的函式...

c 過載 覆蓋 隱藏

成員函式的過載 覆蓋與隱藏 成員函式的過載 覆蓋 override 與隱藏很容易混淆,c 程式設計師必須要搞清楚 概念,否則錯誤將防不勝防。8.2.1 過載與覆蓋 成員函式被過載的特徵 1 相同的範圍 在同乙個類中 2 函式名字相同 3 引數不同 4 virtual 關鍵字可有可無。覆蓋是指派生類函...