1. 程式人生 > >混跡於C++ 之過載與覆蓋(還有隱藏)

混跡於C++ 之過載與覆蓋(還有隱藏)

摘自《高質量程式設計指南》林銳

過載與覆蓋

成員函式被過載的特徵是:

-具有相同的作用域(即同一個類定義中)--如果位於不同的作用域,則為隱藏。

-函式名字相同。

-引數型別/順序或數目不同(包括const引數和非const引數)。

-virtual關鍵字可有可無。

覆蓋是指派生類重新實現(或者改寫)了基類的成員函式,其特徵是:

-不同的作用域(分別位於派生類和基類中)。

-函式名稱相同。

-引數列表相同。

-基類函式必須是虛擬函式。(用virtual關鍵字)--如果沒有virtual關鍵字,則為隱藏。

注:覆蓋:使用虛擬函式virtual 一般不用具體的實現函式virtual fun() = 0;即故意要讓繼承者重新實現函式功。

                   而隱藏則可以暫時在子類裡遮蔽了基類的功能函式,重新實現函式名相同,但引數可以不同

綜上,覆蓋是一種特殊的隱藏。

程式示例1

#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(void)
{
  Derived d;
  Base *pb=&d;
  pb->f(42);     //Base::f(int)=42
  pb->f(3.14f);  //Base::f(float)=3.14
  pb->g();       //Derived::g(void).
  return 0;      
}

有時候,程式設計師希望作“跨越類邊界的過載”,但是過載機制只能作用於同一作用域中,C++提供類

另一種機制--隱藏,它是指派生類的成員函式遮蔽了與其同名的基類成員函式。

雖然還沒達到完美的要求,但C++使用了這種策略(原因《The  Designed and Evolution of C++》).

示例2

#include<iostream>
using namespace std;
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;} }; int main() { Derived d; Base *pb=&d; Derived *pd=&d; //程式的行為僅僅依賴於物件的真實型別 pb->f(3.14f); //動態繫結:Derived::f(float)=3.14 pd->f(3.14f); //動態繫結:Derived::f(float)=3.14 //不好:程式的行為依賴於指標的靜態模型 pb->g(3.14f); //靜態繫結:Base::g(float)=3.14 pd->g(3.14f); //靜態繫結:Derived::g(float)=3 //此處3.14被強制轉化為一個int型別的臨時變數,而本意是想使用跨越類邊界的過載 //不好:程式的行為依賴於指標的靜態模型 pb->h(3.14f); //靜態繫結:Base::h(float)3.14 pd->h(3.14f); //靜態繫結:Derived::g(float)=3 return 0; }


總結:覆蓋是隱藏的一種特殊,它改寫類基類的成員函式,但是隱藏卻沒被改寫成員函式。

           而過載是根據引數的不同,區分使用同一作用域中同名的函式。

另外,

如果確實想使用所謂的“跨越類邊界的過載”,可以在派生類定義中的任何地方顯示的使用using關鍵字,

示例2中紅色處:

寫成 using Base ::g;

         void g(int x){ cout << "Derived::g(int)"<<x<<endl; }

或者使用呼叫傳遞
         void g(float x){Base::g(x);}
         void g(int x){ cout << "Derived::g(int)"<<x<<endl; }
顯然使用using關鍵字比較省事。

引數的預設值的常見錯誤

相關推薦

混跡C++ 過載覆蓋還有隱藏

摘自《高質量程式設計指南》林銳 過載與覆蓋 成員函式被過載的特徵是: -具有相同的作用域(即同一個類定義中)--如果位於不同的作用域,則為隱藏。 -函式名字相同。 -引數型別/順序或數目不同(包括const引數和非const引數)。 -virtual關鍵字可有可無。 覆蓋是

java筆記過載覆蓋

有的時候,類的同一種功能有多種實現方式,到底採用哪種實現方式,取決於呼叫者給定的引數。例如我們最常用的System.out.println()能夠打印出任何資料型別的資料,它有多種實現方式。執行時,Java虛擬機器先判斷給定引數的型別,然後決定執行哪個println()方法(int cha

Java過載覆蓋

有的時候,類的同一種功能有多種實現方式,到底採用哪種實現方式,取決於呼叫者給定的引數。例如我們最常用的System.out.println()能夠打印出任何資料型別的資料,它有多種實現方式。執行時,Java虛擬機器先判斷給定引數的型別,然後決定執行哪個println()方

C邏輯運算符十四

C語言 && || ! 我們在 C 語言中經常會遇到邏輯運算符。|| 是從左向右開始計算的,當遇到為真的條件時停止計算,整個表達式為真;所有條件為假時表達式才為假。 && 是從左向右開始計算,當遇到為假的條件時停止計算,整個表達式為假;所有條件為真時表達式才為真

C++ 異常捕捉處理try...catch...

首先舉一個異常處理的例子: string str = "0123456789"; char ch1 = str[100];    //陣列越界,但是不提醒,程式執行立即崩潰 cout << ch1 << endl;    &n

JNIC/C++的呼叫封裝Demo應用

  專案中使用JNI的地方,如:核心邏輯,金鑰,加密邏輯。JNI還有很多的應用,比如FFMPEG,OpenGL等。 JNI常見的場景如:加解密演算法,音視訊編解碼等。 -- 使用JNI,複用很多優秀的c/c++程式碼:ffmpeg 多媒體播放器;opencv 圖形識別引擎

rabbitmq官方教程釋出訂閱Publish/Subscribe

(using the Java Client) 在上一篇工作佇列中中我們已經建立了一個工作佇列。工作佇列背後的假設是每個任務都交付給一個worker。 在這部分中,我們會做一些完全不同的事情 - 我們會向多個消費者傳遞資訊。這種模式被稱為“釋出/訂閱”。

C++中的過載覆蓋還有(隱藏)

前言 過載(overload)和覆蓋(override)是C++中關於函式的兩個基礎概念,但是如果讓你說出他們具體的描述和區別,一下子還真是不太容易說的很清楚和全面,這裡簡單把記錄一下,作為備忘。關於隱藏我覺得是個誤解,C++中根本沒有隱藏的說法和規則。

C#XML基本讀取XmlDocument物件

XmlDocument doc= new XmlDocument(); XmlElement rootElement; doc.LoadXml("<div>" + result.Replace(@" ", "") + "</

SVN程式碼管理分支合併branch&merge

首先需要安裝TortoiseSVN,我的版本Version 1.9 2015/09/27 18:54:04 (r26833) 1、Check out 在要check out 的路徑右鍵,選擇SVN C

C函數四十

C語言 宏 函數 在 C 語言中,我們經常會遇到函數和宏,那麽我們今天就來分析下函數與宏。 我們先來看看函數與宏有什麽區別:a> 宏是由預處理期直接替換展開的,編譯器不知道宏的存在;b> 函數是由編譯器直接編譯的實體,調用行為由編譯器決定;c> 多次

(1) C++:過載覆蓋隱藏

  C++之中的過載、覆蓋、隱藏   過載 覆蓋 過載與覆蓋的區別 相關程式碼 隱藏   過載 過載是指函式不同的引數表,對同名函式的名稱做修飾,然後這些同名函式就成了不同的函式。在同一可訪問區域內被宣告的幾

菜鳥的C#學習旅——C#方法過載函式過載

目錄 過載 方法過載 函式過載 總結 過載 過載,簡單說,就是函式或者方法有相同的名稱,但是引數列表不相同的情形,這樣的同名不同引數的函式或者方法之間,互相稱之為過載函式或者方法。 過載的

c++中的隱藏過載覆蓋重寫

類過載是c++動態多型,普通函式的過載是靜態多型 成員函式被過載的特徵: (1)相同的範圍(在同一個類中); (2)函式名字相同; (3)引數不同; (4)virtual關鍵字可有可無。  覆蓋是指派生類函式覆蓋基類函式,特徵是: (1)不同的範圍(分別位於派生

C++中過載、重寫覆蓋的區別例項分析

本文例項講述了C++中過載、重寫(覆蓋)和隱藏的區別,對於C++面向物件程式設計來說是非常重要的

JAVA中的基礎-----過載重寫覆蓋的區別:overloadoverride

JAVA中多型的實現機制主要通過overload和override實現。 1)方法的過載:簡言之,就是指同一個類有多個同名的方法,這些方法擁有不同的引數(同名不同參)。可以認為是類中方法的多型性,也稱為編譯時多型。 2)方法的重寫(覆蓋):子類可覆蓋父類的方法,已達到“個性

過載overload覆蓋override的區別

C++中有幾個關鍵詞,原來自己一直都在錯用override(覆蓋或叫改寫、重寫)用於子類對父類的同名函式尤其是虛擬函式的重寫,實現多型overload(過載)函式名相同,引數不同即叫過載,返回值可同也可不同(最早以前必須相同),而且不一定要在類中,在一個作用域中的函式都可過載

C++中過載、重寫覆蓋隱藏的區別例項分析

本文例項講述了C++中過載、重寫(覆蓋)和隱藏的區別,對於C++面向物件程式設計來說是非常重要的概念。具體分析如下: 1.過載:過載從overload翻譯過來,是指同一可訪問區內被宣告的幾個具有不同引數列(引數的型別,個數,順序不同)的同名函式,根據引數列表確定呼叫哪個函式,過載不關心函式返回型

C++中過載、重寫覆蓋隱藏的區別

基本概念: 過載:是指同一可訪問區內被宣告的幾個具有不同引數列(引數的型別,個數,順序不同)的同名函式,根據引數列表確定呼叫哪個函式,過載不關心函式返回型別。 示例: class A{ public: void test(int i); voi

C++過載陣列下標[]圓括號()運算子的方法

#include <iostream> using namespace std; class Matrix { public: Matrix(int, int) ; int& operator()(int, int) ; // 過載圓括號運算子"()" private: