C++中Overload,Override,Hide之間的區(qū)別
一. 簡(jiǎn)介
•Overload: 重載,指函數(shù)同名,但是參數(shù)個(gè)數(shù)不同、或者參數(shù)類(lèi)型不同的多個(gè)實(shí)現(xiàn)。(如果參數(shù)相同但是僅僅返回值不同不是重載,編譯器會(huì)報(bào)錯(cuò)。)
編譯器判斷重載函數(shù):
•第一步,是確定該調(diào)用中所考慮的重載函數(shù)的集合,該函數(shù)集合被稱(chēng)為候選函數(shù)(candidant function)。所謂候選函數(shù)就是與被調(diào)用函數(shù)同名的函數(shù)。
•第二步,分為兩動(dòng)作:第一個(gè)動(dòng)作是編譯器從第一步選出的候選函數(shù)中調(diào)出可行函數(shù)(viable function)??尚泻瘮?shù)的函數(shù)參數(shù)個(gè)數(shù)與調(diào)用的函數(shù)參數(shù)個(gè)數(shù)相同,或者可行函數(shù)的參數(shù)可以多一些,但是多出來(lái)的函數(shù)參數(shù)都要有相關(guān)的缺省值;第二個(gè)動(dòng)作是根據(jù)參數(shù)類(lèi)型的轉(zhuǎn)換規(guī)則將被調(diào)用的函數(shù)實(shí)參轉(zhuǎn)換(conversion)成候選函數(shù)的實(shí)參。這里本著充分利用參數(shù)類(lèi)型轉(zhuǎn)換的原則,換句話說(shuō),盡可能的使用上參數(shù)類(lèi)型轉(zhuǎn)換。當(dāng)然轉(zhuǎn)換要以候選函數(shù)為轉(zhuǎn)換的目標(biāo)。如果依照參數(shù)轉(zhuǎn)換規(guī)則沒(méi)有找到可行函數(shù),則該調(diào)用就是錯(cuò)誤的,則說(shuō)沒(méi)有函數(shù)與調(diào)用匹配,屬于無(wú)匹配情況(no match function)。
•第三步,從第二步中選出的可行函數(shù)中選出最佳可行函數(shù)(best match situation)。在最佳可行函數(shù)的選擇中,從函數(shù)實(shí)參類(lèi)型到相應(yīng)可行函數(shù)參數(shù)所用的轉(zhuǎn)化都要?jiǎng)澐值燃?jí),根據(jù)等級(jí)的劃分(ranked),最后選出最佳可行函數(shù)。
•Override:(想不到比較貼切的翻譯)指在繼承時(shí),父類(lèi)函數(shù)聲明為 virtual , 子類(lèi)重新聲明和實(shí)現(xiàn)該函數(shù)(函數(shù)名和參數(shù)完全相同,返回值不做約束)。子類(lèi)該函數(shù)可以聲明為 virtual ,也可以不加,不做限制,但是如果該子類(lèi)還會(huì)繼續(xù)被重載,則最好也聲明為 virtual 。正是因?yàn)橛衯irtual和Override的機(jī)制,C++才能夠?qū)崿F(xiàn)多態(tài)。
•Hide:繼承結(jié)構(gòu)中的函數(shù)隱藏,指父類(lèi)中聲明了函數(shù),子類(lèi)中聲明和定義了完全一致的函數(shù),但是父類(lèi)中函數(shù)沒(méi)有聲明為vitual,此時(shí)子類(lèi)中的同名同參數(shù)函數(shù)會(huì)完全隱藏父類(lèi)的函數(shù)。貌似和Override很像,但是其實(shí)現(xiàn)機(jī)制和Override完全不同,且會(huì)導(dǎo)致問(wèn)題,應(yīng)該避免使用。( virtual機(jī)制是使用虛表(vtable)實(shí)現(xiàn)的,虛表維護(hù)一個(gè)虛函數(shù)指針列表,但一個(gè)對(duì)象的某個(gè)虛函數(shù)被調(diào)用的時(shí)候,去虛表中查找并決定調(diào)用的是哪個(gè)函數(shù),具體的實(shí)現(xiàn),小編下次在講。)
class Super
{
public:
void go() { cout << "go() called on Super" << endl; }
};
class Sub : public Super
{
public:
void go() { cout << "go() called on Sub" << endl; }
};
Sub mySub;
mySub.go(); // output: go() called on Sub
Super& ref = mySub;
ref.go(); //output: go() called on Super
也許你希望它會(huì)調(diào)用子類(lèi)的函數(shù),但這可能和你的預(yù)期完全不同。
二. 總結(jié)
重載overload,這個(gè)概念是大家熟知的。在同一可訪問(wèn)區(qū)內(nèi)被聲名的幾個(gè)具有不同參數(shù)列的(參數(shù)的類(lèi)型、個(gè)數(shù)、順序不同)同名函數(shù),程序會(huì)根據(jù)不同的參數(shù)列來(lái)確定具體調(diào)用哪個(gè)函數(shù),這種機(jī)制就是重載。重載不關(guān)心函數(shù)的返回值類(lèi)型,即返回類(lèi)型不同無(wú)法構(gòu)成重載。此外,C++ 中的const成員函數(shù)也可以構(gòu)成overload。
總結(jié)一下重載的特征:
1、處在相同的空間中,即相同的范圍內(nèi);
2、函數(shù)名相同;
3、參數(shù)不同,即參數(shù)個(gè)數(shù)不同,或相同位置的參數(shù)類(lèi)型不同;
4、const成員函數(shù)可以和非const成員函數(shù)形成重載;
5、virtual關(guān)鍵字、返回類(lèi)型對(duì)是否夠成重載無(wú)任何影響。
覆蓋override,是指派生類(lèi)中存在重新定義的函數(shù),其函數(shù)名、參數(shù)列、返回值類(lèi)型必須同父類(lèi)中的相對(duì)應(yīng)被覆蓋的函數(shù)嚴(yán)格一致,覆蓋函數(shù)和被覆蓋函數(shù)只有函數(shù)體(花括號(hào)中的部分)不同,當(dāng)派生類(lèi)對(duì)象調(diào)用子類(lèi)中該同名函數(shù)時(shí)會(huì)自動(dòng)調(diào)用子類(lèi)中的覆蓋版本,而不是父類(lèi)中的被覆蓋函數(shù)版本,這種機(jī)制就叫做覆蓋,特征是:
1、不同的范圍(分別位于派生類(lèi)與基類(lèi));
2、函數(shù)名字相同;
3、參數(shù)相同;
4、基類(lèi)函數(shù)必須有virtual關(guān)鍵字。
針對(duì)上述兩個(gè)概念,還有一個(gè)隱藏hide。所謂的隱藏,指的是派生類(lèi)類(lèi)型的對(duì)象、指針、引用訪問(wèn)基類(lèi)和派生類(lèi)都有的同名函數(shù)時(shí),訪問(wèn)的是派生類(lèi)的函數(shù),即隱藏了基類(lèi)的同名函數(shù)。隱藏規(guī)則的底層原因其實(shí)是C++的名字解析過(guò)程。在繼承機(jī)制下,派生類(lèi)的類(lèi)域被嵌套在基類(lèi)的類(lèi)域中。派生類(lèi)的名字解析過(guò)程如下:
1、首先在派生類(lèi)類(lèi)域中查找該名字。
2、如果第一步中沒(méi)有成功查找到該名字,即在派生類(lèi)的類(lèi)域中無(wú)法對(duì)該名字進(jìn)行解析,則編譯器在外圍基類(lèi)類(lèi)域?qū)Σ檎以撁值亩x。
總結(jié)一下隱藏的特征:
1、如果派生類(lèi)的函數(shù)與基類(lèi)的函數(shù)同名,但是參數(shù)不同。此時(shí),不論有無(wú)virtual關(guān)鍵字,基類(lèi)的函數(shù)將被隱藏(注意別與重載混淆)。
2、如果派生類(lèi)的函數(shù)與基類(lèi)的函數(shù)同名,并且參數(shù)也相同,但是基類(lèi)函數(shù)沒(méi)有virtual關(guān)鍵字。此時(shí),基類(lèi)的函數(shù)被隱藏(注意別與覆蓋混淆)。
相關(guān)文章
QT5交叉編譯入門(mén)級(jí)教程(arm64、mips64)
交叉編譯就是在當(dāng)前系統(tǒng)平臺(tái)上,開(kāi)發(fā)編譯運(yùn)行于其它平臺(tái)的程序,比如本文硬件環(huán)境是x86平臺(tái),但是編譯出來(lái)的程序是在arm64架構(gòu)、mips64等架構(gòu)上運(yùn)行,本文給大家分享QT5交叉編譯入門(mén)級(jí)教程(arm64、mips64),感興趣的朋友一起看看吧2023-11-11C語(yǔ)言實(shí)現(xiàn)班級(jí)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)班級(jí)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11C++實(shí)現(xiàn)完整功能的通訊錄管理系統(tǒng)詳解
來(lái)了來(lái)了,通訊錄管理系統(tǒng)踏著七彩祥云飛來(lái)了,結(jié)合前面的結(jié)構(gòu)體知識(shí)和分文件編寫(xiě)方法,我總結(jié)并碼了一個(gè)帶菜單的通訊錄管理系統(tǒng),在這篇文章中將會(huì)提到C的清空屏幕函數(shù),嵌套結(jié)構(gòu)體具體實(shí)現(xiàn),簡(jiǎn)單且充實(shí),跟著我的思路,可以很清晰的解決這個(gè)項(xiàng)目2022-05-05Qt?10進(jìn)制和16進(jìn)制轉(zhuǎn)換的使用示例
在編程過(guò)程中,處理16進(jìn)制字符串與10進(jìn)制數(shù)字之間的轉(zhuǎn)換是很常見(jiàn)的需求,本文主要介紹了Qt?10進(jìn)制和16進(jìn)制轉(zhuǎn)換的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09C++ 讀取文件內(nèi)容到指定類(lèi)型的變量方法
今天小編就為大家分享一篇C++ 讀取文件內(nèi)容到指定類(lèi)型的變量方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07