重載(overload)與重寫(override)

提綱.png

一.C++中的重寫瑞凑、重載会喝、重定義

1.重載(overload)

概念

同一個(gè)類中的函數(shù)具有相同的名稱陡叠,但是參數(shù)的列表不相同的情形,這樣的同名不同參數(shù)的函數(shù)之間肢执,互成為重載函數(shù)枉阵。

基本條件
  • 同一個(gè)類中(相同的作用域中)
  • 函數(shù)名稱必須相同
  • 函數(shù)參數(shù)必須不相同,可以是參數(shù)類型或者參數(shù)個(gè)數(shù)不同
  • 函數(shù)的返回值可以不同

2.重寫(override)

概念

也稱為覆蓋预茄,子類重新定義的父類中有相同的名稱或者參數(shù)的虛函數(shù)兴溜,主要在繼承關(guān)系中出現(xiàn)。

基本條件
  • 子類重寫父類中的virtual函數(shù)
  • 重寫函數(shù)和被重寫函數(shù)的函數(shù)名和參數(shù)必須一致(具體實(shí)現(xiàn)一般不同)
  • 重寫函數(shù)和被重寫函數(shù)的返回值相同,要么都返回指針昵慌,要么都返回引用
  • 重寫函數(shù)和被重寫函數(shù)都是virtual函數(shù)(其中重載函數(shù)可以帶virtual假夺,也可以不帶)
注意
  • 靜態(tài)方法不能被重寫,也就是static和virtual不能同時(shí)使用
  • C++ 11中新增了final關(guān)鍵字斋攀,final修飾的虛函數(shù)不能被被重寫

3.重定義(redefining)

注意

也叫隱藏已卷,子類重定義父類中的非虛函數(shù),屏蔽了父類的同名函數(shù)(相當(dāng)于創(chuàng)建了一個(gè)新的函數(shù)淳蔼,跟父類無(wú)關(guān))

基本條件
  • 子類和父類函數(shù)的名稱相同侧蘸,參數(shù)也相同,父類中的函數(shù)不是virtual鹉梨,父類的函數(shù)將被隱藏
  • 子類和父類的函數(shù)名稱相同讳癌,但參數(shù)不同,此時(shí)不管父類函數(shù)是不是virtual函數(shù)存皂,都將被隱藏晌坤。

4.深入理解C++中的重寫(override)與重定義(redefining)

上面我們對(duì)C++中的重寫(override)與重定義(redefining)做了概念上的區(qū)分,只要記住上面的概念特征就嗯呢該區(qū)分這兩種操作旦袋,下面我們來(lái)從原理上說(shuō)明下這兩種操作有什么區(qū)別:

重寫(override)

上面我們已經(jīng)說(shuō)了骤菠,C++中重寫的時(shí)候重寫的是父類中的虛函數(shù)(virtual),因此我們需要從虛函數(shù)的工作原理說(shuō)起。
??由于對(duì)于沒(méi)有使用virtual的函數(shù)疤孕,程序?qū)⒏鶕?jù)引用類型或指針類型選擇方法商乎;如果使用了virtual,程序?qū)⒏鶕?jù)引用或指針指向的對(duì)象類型來(lái)選擇方法祭阀,因此對(duì)于虛函數(shù)鹉戚,到底使用哪個(gè)函數(shù)(父類或者子類中的函數(shù))是不能再編譯器確定的,因?yàn)榫幾g器不知道指針或者引用指向的是哪種對(duì)象专控,故編譯器需要在程序運(yùn)行時(shí)選擇正確的虛方法的代碼,這被稱為動(dòng)態(tài)聯(lián)編抹凳。為了是動(dòng)態(tài)聯(lián)編能夠在運(yùn)行時(shí)正確的進(jìn)行決策,必須采用一些跟蹤基類的指針或者引用指向的對(duì)象類型踩官。

通常却桶,編譯器處理虛函數(shù)的方法是:給每個(gè)對(duì)象添加一個(gè)隱藏成員。隱藏成員中保存了一個(gè)指向虛函數(shù)表的指針蔗牡。虛函數(shù)表是一個(gè)保存函數(shù)地址的數(shù)組颖系,每一個(gè)地址都對(duì)應(yīng)該類中的一個(gè)虛函數(shù)”缭剑基類對(duì)象包含一個(gè)指針嘁扼,該指針指向基類中所有虛函數(shù)的地址表。派生類對(duì)象將包含一個(gè)指向自己(獨(dú)立)虛函數(shù)表的指針黔攒。
??如果派生類重寫(override)了虛函數(shù)趁啸,則派生類的虛函數(shù)表將保存新函數(shù)的地址强缘。

虛函數(shù)的工作原理.jpg

因此,當(dāng)用指針調(diào)用一個(gè)函數(shù)時(shí)不傅,回去指針?biāo)笇?duì)象的虛函數(shù)表中去查找被重寫后的虛函數(shù)旅掂。

重定義(redefining)

參照隱藏規(guī)則,派生類的成員函數(shù)隱藏了基類的同名函數(shù)访娶。所謂隱藏就是指派生類類型的對(duì)象商虐、引用、指針訪問(wèn)基類和派生類都有的同名函數(shù)的時(shí)候崖疤,訪問(wèn)的是派生類的函數(shù)秘车,隱藏了基類同名函數(shù)。派生類既然自動(dòng)繼承了基類的成員劫哼,那么基類成員就可以被派生類直接訪問(wèn)叮趴,那么為什么訪問(wèn)的是派生類的成員函數(shù)呢?所以隱藏 規(guī)則實(shí)際上就是默認(rèn)的c++名字解析過(guò)程权烧。
??在繼承機(jī)制下眯亦,派生類的類域被嵌套在基類的類域中,派生類的名字解析過(guò)程如下:

  • 1)首先在派生類中查找改名字
  • 2)如果第一步未查找到豪嚎,及派生類的類域?qū)Ω拿譄o(wú)法進(jìn)行解析搔驼,則編譯器在外圍基類類域查找改名字的定義

所以準(zhǔn)確來(lái)說(shuō)谈火,當(dāng)派生類和基類有同一名字的成員時(shí)侈询,派生類成員是隱藏了對(duì)基類成員的直接訪問(wèn)。那么如果要訪問(wèn)基類同名成員呢糯耍?加上類作用域限定例如:Base::g(float)就可以了扔字。

二.Java 方法重載和重寫

1.重載(overload)

Java中的重載和C++中的基本一致,這里再?gòu)?qiáng)調(diào)一下:

  • 重載的方法必須具有不同的參數(shù)列表
  • 重載的方法可以有不同的返回值類型
  • 重載的方法可以有不同的訪問(wèn)修飾符

2.重寫(override)

若子類中聲明的方法與父類中的某一方法具有相同的方法名温技、返回值類型和參數(shù)列表革为,則子類中的方法將覆蓋父類中的方法。 如需要調(diào)用父類中原有的方法舵鳞,可以使用super關(guān)鍵字震檩,該關(guān)鍵字引用了當(dāng)前類的父類

方法重寫的規(guī)則如下:

  • 重寫方法的參數(shù)列表必須與被重寫方法的參數(shù)列表完全相同
  • 重寫方法的返回值類型必須與被重寫方法的返回值類型完全相同
  • 重寫方法的訪問(wèn)權(quán)限不能比被重寫方法的訪問(wèn)權(quán)限更嚴(yán)格蜓堕。比如:如果父類的一個(gè)方法被聲明為public抛虏,那么在子類中重寫該方法就不能聲明為protected
  • 聲明為final的方法不能被重寫
  • 聲明為static的方法不能被重寫,但是能夠在子類中再次聲明套才,父類中的static方法會(huì)被隱藏
  • 子類和父類在同一個(gè)包中迂猴,那么子類可以重寫父類所有方法,除了聲明為private和final的方法
  • 子類和父類不在同一個(gè)包中背伴,那么子類只能夠重寫父類的聲明為public和protected的非final方法
  • 構(gòu)造方法不能被重寫

3.Java沒(méi)有“重定義”這個(gè)概念

三.重寫的意義

重寫伴隨著繼承沸毁,他的的意義主要在于實(shí)現(xiàn)多態(tài)峰髓,用父類的引用來(lái)操作子類對(duì)象,但在實(shí)際的運(yùn)行中對(duì)象將運(yùn)行自己重寫的方法息尺。
??實(shí)際應(yīng)用中携兵,用得最多的一種運(yùn)行時(shí)多態(tài),就是用只知道父類型(可能是類搂誉,更多的可能是接口)的定義眉孩,這樣只能調(diào)用父類型的方法,繼承該父類并重寫該方法的子類勒葱,就會(huì)自動(dòng)執(zhí)行重寫了的方法(這在大型軟件里很常用浪汪,父類型和子類型可能是不同的人編寫的,以利于協(xié)作編程)凛虽。

public class OverrideTest {
    public static void main (String[] args) {
        Animal h = new Horse();
        h.eat();

        Opertion o = new Horse();
        o.run(30);

    }
}

class Animal {
    public void eat(){
        System.out.println ("Animal is eating.");
    }
}

class Horse extends Animal implements Opertion{
    public void eat(){
        System.out.println ("Horse is eating.");
    }
    public void buck(){
    }
    @Override
    public void run(int time) {
        System.out.println ("Horse is run: "+ time +"s");
    }
}
public interface Opertion {
    void run(int time);
}

輸出為:

Horse is eating.
Horse is run: 30s

在Java中死遭, Animal h = new Horse(); 中引用h指向子類Horse對(duì)象,因此其調(diào)用的也是子類Horse的eat方法凯旋。但是呀潭,如果調(diào)用子類特有的方法,如上例的h.buck(); 會(huì)出現(xiàn)編譯錯(cuò)誤至非,除非強(qiáng)制轉(zhuǎn)換為子類對(duì)象((Horse) h).buck();钠署。
??同時(shí)需要注意的是向上轉(zhuǎn)形是自動(dòng)的,即Animal h = new Horse();父類的引用指向子類對(duì)象是可以的荒椭,但是子類的引用指向父類對(duì)象就是錯(cuò)的谐鼎,必須顯示的進(jìn)行強(qiáng)制轉(zhuǎn)換。

C++中由于動(dòng)態(tài)聯(lián)編趣惠,指針或者引用指向的虛函數(shù)可能會(huì)與上述行為略有不同狸棍。

四.Java和C++的一些比較

1.Java和C++中的重寫

可以看到,Java中重寫只要寫一個(gè)和父類函數(shù)同名同參數(shù)的同返回值類型的函數(shù)即可(這在C++中就是“重定義”)味悄,不需要抽象函數(shù)(即C艸中的虛函數(shù))草戈,因此Java中的普通函數(shù)就能起到C艸中虛函數(shù)的作用。

2.Java中為什么沒(méi)有“重定義”侍瑟?

上面我們說(shuō)了唐片,只要是一個(gè)和父類函數(shù)同名同參數(shù)的同返回值類型的函數(shù),不管加沒(méi)加“@override”注解涨颜,他就是重寫的函數(shù)费韭。此時(shí)這個(gè)重載的函數(shù)就相當(dāng)于C艸中“重定義”的函數(shù)。只不過(guò)Java中需要用super關(guān)鍵字來(lái)調(diào)用父類中的函數(shù)(需要參數(shù)相同)咐低,而C++中需要用作用域解析運(yùn)算符“::”來(lái)調(diào)用父類中的方法揽思。

3. Java抽象函數(shù)與C++純虛函數(shù)

Java中沒(méi)有虛函數(shù)的概念,因?yàn)镃++的虛函數(shù)是用來(lái)讓子類重寫的见擦,然而Java中普通方法就可以被子類重寫钉汗,因此沒(méi)有必要用虛函數(shù)羹令。
??Java中的抽象函數(shù)相當(dāng)于C艸中的純虛函數(shù),兩者換湯不換藥:

  • C++中純虛函數(shù)形式為:virtual void print() = 0;
  • Java中純虛函數(shù)形式為:abstract void print();

4.Java抽象類與C++抽象類

C++類中只要含有一個(gè)純虛函數(shù)损痰,該類就是抽象類
??Java抽象類是用abstract修飾聲明的類福侈,當(dāng)然類中至少要含有一個(gè)抽象方法,不然聲明的抽象類沒(méi)有意義

5.Java接口和C++虛基類

接口的存在是為了形成一種規(guī)約卢未,他更多是對(duì)“行為”的一種抽象(抽象類是對(duì)“屬性”的一種約束)肪凛。在三種的例子中我們也定義了一個(gè)接口
??接口中的方法會(huì)被隱式地指定為public abstract,接口中的變量會(huì)被隱式地指定為public static final變量辽社,并且接口中所有的方法不能有具體的實(shí)現(xiàn)伟墙,也就是說(shuō),接口中的方法必須都是抽象方法滴铅。從這里可以隱約看出接口和抽象類的區(qū)別戳葵,接口是一種極度抽象的類型,它比抽象類更加“抽象”汉匙,并且一般情況下不在接口中定義變量拱烁。

  • C++中接口其實(shí)就是全虛基類。
  • Java中接口是用interface修飾的類噩翠。

6. 小結(jié)

  • C++虛函數(shù) == Java普通函數(shù)
  • C++純虛函數(shù) == Java抽象函數(shù)
  • C++虛基類 == Java抽象類
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末戏自,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子伤锚,更是在濱河造成了極大的恐慌擅笔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件见芹,死亡現(xiàn)場(chǎng)離奇詭異剂娄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)玄呛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)和二,“玉大人徘铝,你說(shuō)我怎么就攤上這事」呗溃” “怎么了惕它?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)废登。 經(jīng)常有香客問(wèn)我淹魄,道長(zhǎng),這世上最難降的妖魔是什么堡距? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任甲锡,我火速辦了婚禮兆蕉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缤沦。我一直安慰自己虎韵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布缸废。 她就那樣靜靜地躺著包蓝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪企量。 梳的紋絲不亂的頭發(fā)上测萎,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音届巩,去河邊找鬼绳泉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛姆泻,可吹牛的內(nèi)容都是我干的零酪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拇勃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼四苇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起方咆,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤月腋,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后瓣赂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體榆骚,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年煌集,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妓肢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苫纤,死狀恐怖碉钠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卷拘,我是刑警寧澤喊废,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站栗弟,受9級(jí)特大地震影響污筷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乍赫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一瓣蛀、第九天 我趴在偏房一處隱蔽的房頂上張望陆蟆。 院中可真熱鬧,春花似錦揪惦、人聲如沸遍搞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)溪猿。三九已至,卻和暖如春纫塌,著一層夾襖步出監(jiān)牢的瞬間诊县,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工措左, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留依痊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓怎披,卻偏偏與公主長(zhǎng)得像胸嘁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凉逛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 重載與重寫是Java面向?qū)ο缶幊痰闹匾拍睢?重寫(Override)重寫是子類繼承父類后性宏,對(duì)父類允許訪問(wèn)(子類有...
    冷月的帥哥閱讀 301評(píng)論 0 0
  • 1.C和C++的區(qū)別?C++的特性状飞?面向?qū)ο缶幊痰暮锰帲?答:c++在c的基礎(chǔ)上增添類毫胜,C是一個(gè)結(jié)構(gòu)化語(yǔ)言,它的重...
    杰倫哎呦哎呦閱讀 9,478評(píng)論 0 45
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • (一)Java部分 1诬辈、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,071評(píng)論 0 62
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用酵使。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 4,573評(píng)論 1 114