C++中的重載、覆蓋、隱藏介紹
前幾天面試時被問及C++中的覆蓋、隱藏,概念基本答不上來,只答了怎么用指針實現(xiàn)多態(tài),也還有遺漏。最終不歡而散?;貋砗笤诰W(wǎng)上查找學(xué)習(xí)了一番,做了這個總結(jié)。其中部分文字借用了別人的博客,望不要見怪。
•概念
一、重載(overload)
指函數(shù)名相同,但是它的參數(shù)表列個數(shù)或順序,類型不同。但是不能靠返回類型來判斷。
(1)相同的范圍(在同一個作用域中) ;
(2)函數(shù)名字相同;
(3)參數(shù)不同;
(4)virtual 關(guān)鍵字可有可無。
(5)返回值可以不同;
二、重寫(也稱為覆蓋 override)
是指派生類重新定義基類的虛函數(shù),特征是:
(1)不在同一個作用域(分別位于派生類與基類) ;
(2)函數(shù)名字相同;
(3)參數(shù)相同;
(4)基類函數(shù)必須有 virtual 關(guān)鍵字,不能有 static 。
(5)返回值相同(或是協(xié)變),否則報錯;<—-協(xié)變這個概念我也是第一次才知道…
(6)重寫函數(shù)的訪問修飾符可以不同。盡管 virtual 是 private 的,派生類中重寫改寫為 public,protected 也是可以的
三、重定義(也成隱藏)
(1)不在同一個作用域(分別位于派生類與基類) ;
(2)函數(shù)名字相同;
(3)返回值可以不同;
(4)參數(shù)不同。此時,不論有無 virtual 關(guān)鍵字,基類的函數(shù)將被隱藏(注意別與重載以及覆蓋混淆) 。
(5)參數(shù)相同,但是基類函數(shù)沒有 virtual關(guān)鍵字。此時,基類的函數(shù)被隱藏(注意別與覆蓋混淆) 。
•例子
#include <iostream> using namespace std; class SParent { public: SParent( ){}; SParent( const SParent &p ) { cout << "parent copy construct" << endl; } int add( int a,int b ) { cout << "parent int add" << endl; return a + b; } double add( double a,double b ) { cout << "parent double add" << endl; return a + b; } virtual int dec( int a,int b ) { cout << "parent int dec" << endl; return a - b; } }; class SChild : public SParent { public: //using SParent::add; float add( float a,float b ) { cout << "child float add" << endl; return a + b; } int dec(int a, int b) { cout << "child int dec" << endl; return a - b; } }; int main() { /* 測試重載 */ SParent parent; parent.add( 3,5 ); parent.add( (double)3,(double)5 ); cout << endl; /* 測試覆蓋 */ SChild *pchild = (SChild *)new SParent();/* 基類強(qiáng)轉(zhuǎn)為子類...危險...,用dynamic_cast轉(zhuǎn)換也不行 */ pchild->dec( 10,3 ); SParent *pparent = new SChild(); pparent->dec( 11,3 ); cout << endl; /* 測試隱藏 */ SChild child; child.add( (int)3,(int)5 ); cout << endl; /* 測試函數(shù)表 */ ((SParent *)NULL)->add( 4,6 ); ((SChild *)NULL)->add( 4,6 ); int a = 0; ((SChild *)&a)->add( 4,6 ); cout << endl; /* 測試函數(shù)地址 */ ((SParent)child).add( (int)4,(int)8 ); child.SParent::add( 3,5 ); return 0; }
輸出結(jié)果:
parent int add parent double add parent int dec child int dec child float add parent int add child float add child float add parent copy construct parent int add parent int add 按 <RETURN> 來關(guān)閉窗口...
•理解
int SParent::add(int a,int b)與double SParent::add( double a,double b )是重載
int SParent::add(int a,int b)與double SParent::add( double a,double b )都被子類SChild中的float SChild::add( float a,float b )隱藏
int SParent::dec( int a,int b )被子類SChild中的int SChild::dec( int a,int b )覆蓋
•測試
1.重載測試,簡單易懂,略過。
2.覆蓋測試。dec函數(shù)在基類、子類中同名同參,為虛函數(shù),故稱覆蓋。
SChild *pchild = (SChild *)new SParent()創(chuàng)建的是一個基類對象,其函數(shù)表應(yīng)該為
SParent *pparent = new SChild();創(chuàng)建一個子類對象,其函數(shù)表應(yīng)該為
由上面的函數(shù)表可見,當(dāng)發(fā)生覆蓋時,子類的函數(shù)名會把基類的同名函數(shù)覆蓋(這也就是為什么叫覆蓋的原因吧)。這樣我們可以利用一個指向子類的基類指針實現(xiàn)多態(tài)。但重點只有一
個,就是函數(shù)表里到底指向誰(不管這個指針經(jīng)過轉(zhuǎn)換后是什么類型的).故輸出分別為父類、子類。這是一個運行時多態(tài)。
3.隱藏測試
int SParent::add(int a,int b)與double SParent::add( double a,double b )都被子類SChild中的float SChild::add( float a,float b )覆蓋,是因為他們同名,而且在不同的作用域中(基類、子類作用域是不同的)。child.add( (int)3,(int)5 );這行代碼中,編譯器在子類中查找add函數(shù),只找到了一個(基類的add(int a,int b)會被編譯根據(jù)隱藏規(guī)則略過),再根據(jù)隱式類型轉(zhuǎn)換發(fā)現(xiàn)該函數(shù)適用。如果無法隱式轉(zhuǎn)換,則編譯不過。隱藏的原因:防止隱式類型轉(zhuǎn)換造成錯誤。比如int也是可以轉(zhuǎn)換成char的,假如基類有一函數(shù)add(char a,char b),子類也有一函數(shù)add(double a,double b)。程序員想著在子類隱式把int轉(zhuǎn)換為double,但編譯器可能調(diào)的是基類的。這也防止了一些庫或封裝好的基類對程序員造成困擾。
像上面的代碼,如果你確實需要基類的函數(shù),可以用using SParent:add。則把基類的add函數(shù)域擴(kuò)大到了子類,構(gòu)成重載。
4.函數(shù)表測試
上面我們說到函數(shù)表,這個是在編譯時定好的,程序運行時加載到內(nèi)存中。這意味著我們可以直接通過地址去調(diào)用函數(shù)。所以((SChild *)NULL)->add( 4,6 );這種代碼也是能運行通過的。網(wǎng)上還有人通過計算直接取到了函數(shù)表的地址直接調(diào)用了。但這種代碼不安全不規(guī)范不說,還有個更大的問題。當(dāng)成員函數(shù)里需要調(diào)用成員變量時,通過這種假的對象指針肯定找不到成員變量表,直接訪問了非法內(nèi)存。
5.函數(shù)地址測試
有了隱藏、覆蓋,哪么我們要怎么調(diào)用被隱藏、覆蓋的函數(shù)呢。下面有兩種方法:
((SParent)child).add( (int)4,(int)8 );
child.SParent::add( 3,5 );
第一種是比較低效的方法。事實上它是通過拷貝構(gòu)造函數(shù)生成一個臨時的基類變量去調(diào)用基類的add函數(shù)。
第二種通過::指定域去訪問。這種方法是編譯器根據(jù)域直接找到了基類的函數(shù)地址,跟函數(shù)表沒有多大關(guān)系。
上一篇:C++動態(tài)規(guī)劃之最長公子序列實例
欄 目:C語言
本文標(biāo)題:C++中的重載、覆蓋、隱藏介紹
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3105.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 04-02jquery與jsp,用jquery
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實例總結(jié)