混跡於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
JNI與C/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中的基礎-----過載與重寫(覆蓋)的區別:overload與override
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: