1. 程式人生 > >C++中過載、覆蓋和隱藏的區別,以及適用場景

C++中過載、覆蓋和隱藏的區別,以及適用場景

一、過載、覆蓋和隱藏的區別

二、適用場景

1、過載:

  適用於不同的資料型別都需要使用到的功能函式。以資料相加的函式為例,可以在同一個檔案內提供以下的過載函式以支援同樣的功能:

  int add(int, int);/*2個整數相加*/

  int add(int, int, int);/*3個整數相加*/

  double add(double, double);/*2個double型相加*/

  特別的,形參為指標或引用時,指向的物件分別const和非const的情況,可以過載。比如下方的合併2個string的重置函式,根據實參的型別是否是const,編譯器可以自動選擇呼叫哪個:

  string &stringCat(string*, string*);/*指向非const的*/

  const string &stringCat(const string*, const string*)/*指向const,編譯通過,因為指標或引用指向的物件的型別不同*/

  string &stringCat(string* const, string* const);/*編譯報錯。因為非const的引數可以轉換為const的,在傳入非const實參時第1和第3個函式都適用,所以編譯器認為1和3重複定義*/

  編譯器會根據引數的型別、引數數量,自動選擇匹配的函式。注意引數相同、返回值型別不同的同名函式,不是過載的,編譯時會報錯。

2、覆蓋:

  只能在類的繼承中使用。適用於父類和子類都要實現的成員函式,且該函式需要在執行中動態繫結的,這個函式就是虛擬函式,在動態繫結中子類的虛擬函式把父類的覆蓋了。

  class Base{public: virtual func();};/*基類用virtual關鍵字定義了一個func()虛擬函式*/

  class Child : public Base{public: func();};/*子類定義了一個同名、同參數、同返回值的函式,即是覆蓋*/

  Base  *pB; Bash B; Child C;

  pB = &B; pB->func();/*動態繫結為Base物件,執行Base的func*/

  pB = &C; pB->func();/*動態繫結為Child物件,執行Child的func*/

  程式在執行時動態解析指標或引用指向的物件屬於哪個類,從而決定呼叫哪個類的成員函式。

3、隱藏

  內層作用域的同名函式或同名變數,會影響外層作用域的同名函式和物件。唯一的例外就是虛擬函式的覆蓋。

  一般建議除了通過覆蓋方式繼續來的虛擬函式外,派生的子類裡不要出現父類中使用的名字,避免隱藏。

三、其他一些技巧

1、虛擬函式也能過載

  類的成員函式,無論是否是虛擬函式,都能被過載。但是如果派生類對虛擬函式進行覆蓋,則相應的過載函式會被隱藏。那麼問題來了,派生類怎麼才能訪問到這些隱藏的函式呢?

  方法一:把所有過載函式都覆蓋一遍。

  方法二:使用作用域說明符,顯式說明呼叫的物件。

  方法三:使用using宣告語句,將外層的名稱拉入內層。這時派生類只需要實現部分的虛擬函式覆蓋,其他函式自動變為可見的過載函式。