課程
/后端開發(fā)
/C++
/C++遠(yuǎn)征之多態(tài)篇
如果在父類中定義了虛函數(shù) 子類中沒有同名的虛函數(shù),那么子類公有繼承父類時會把虛函數(shù)繼承過去嗎
2015-12-28
源自:C++遠(yuǎn)征之多態(tài)篇 2-2
正在回答
不一定,如果是private權(quán)限的,就不會,其它情況會,這樣就算不是虛函數(shù)也是一樣的。
子類繼承父類,在創(chuàng)建類的時候就會有一個虛函數(shù)表的概念,如果子類沒重寫同名函數(shù),子類的虛函數(shù)表關(guān)于該函數(shù)的入口地址就會指向父類的該函數(shù)的代碼入口地址
qq_圓圓_0 提問者
父類函數(shù)如果是虛函數(shù),子類的同名函數(shù)(參數(shù)也要相同哦)就一定是虛函數(shù),子類的子類也一樣
父類函數(shù)不是虛函數(shù),子類同名函數(shù)是虛函數(shù),編譯是沒有問題的,如果沒有父類指針指向子類對象的操作也是沒有問題的,但是有父類指針指向子類對象的操作時,操作的函數(shù)會是父類的函數(shù),至此都沒有什么問題,但是在父類的指針釋放內(nèi)存時,系統(tǒng)就會出問題。這時候如果子類還有孫子類,那么子類指針指向?qū)O子類以及重孫子類,都會是覆蓋,也就是調(diào)用同名函數(shù)的時候,執(zhí)行的都是實際對象的函數(shù)實現(xiàn)。但是父類指針指向?qū)O子類以及重孫子類與指向子類的效果是一樣的。這是我 實測的結(jié)果,在delete父類指針時,內(nèi)存無法釋放,系統(tǒng)就出問題了。
我分析了一下,父類函數(shù)不是虛函數(shù),在子類修飾為虛函數(shù),這時候,父類的虛函數(shù)表中指向假設(shè)0x12345內(nèi)存地址,子類的虛函數(shù)表也應(yīng)該是指向0x12345,這樣在實例化類的時候,由于父類中該函數(shù)是非virtual的,子類的指向也不會變,所以執(zhí)行結(jié)果就是父類與子類的該函數(shù)執(zhí)行父類的函數(shù)實現(xiàn)。父類指針指向?qū)O子類的時候,孫子類的虛函數(shù)表由于子類聲明為虛函數(shù),就指向假設(shè)0x67890內(nèi)存地址,由于父類的該函數(shù)是非virtual的,所以孫子類對象的該函數(shù)在虛函數(shù)表中要以父類的地址為準(zhǔn),而不會用0x67890覆蓋掉父類的0x12345,所以執(zhí)行結(jié)果仍是父類的實現(xiàn)。這時候子類指針指向?qū)O子類的時候,就與咱學(xué)的一樣嘍,執(zhí)行結(jié)果是孫子類的實現(xiàn)。
再來說一下釋放內(nèi)存出的問題,具體我還真分析不出來,不過如果父類的析構(gòu)函數(shù)是虛析構(gòu)函數(shù)的話,內(nèi)存的釋放也是沒有問題的,所以我們其它的不管(不管業(yè)務(wù)是否有業(yè)務(wù)需要),析構(gòu)函數(shù)最好都加上virtual關(guān)鍵字。對于如果有可能被繼承的類,其函數(shù)最好都聲明稱虛函數(shù),這樣繼承才有意義,才可以讓你的邏輯在運(yùn)行時決定使用哪個具體實現(xiàn)(多態(tài))。virtual應(yīng)該就是為了實現(xiàn)面向?qū)ο笾械亩鄳B(tài)才誕生的吧
不用不好意思,學(xué)習(xí)哪不會說出來咱們一起討論,吃透了,學(xué)會了才是我們的目的。
太陽雨下 回復(fù) qq_圓圓_0 提問者
舉報
本教程將帶領(lǐng)大家體會面向?qū)ο笕筇匦灾械亩鄳B(tài)特性
Copyright ? 2025 imooc.com All Rights Reserved | 京ICP備12003892號-11 京公網(wǎng)安備11010802030151號
購課補(bǔ)貼聯(lián)系客服咨詢優(yōu)惠詳情
慕課網(wǎng)APP您的移動學(xué)習(xí)伙伴
掃描二維碼關(guān)注慕課網(wǎng)微信公眾號
2015-12-29
不一定,如果是private權(quán)限的,就不會,其它情況會,這樣就算不是虛函數(shù)也是一樣的。
子類繼承父類,在創(chuàng)建類的時候就會有一個虛函數(shù)表的概念,如果子類沒重寫同名函數(shù),子類的虛函數(shù)表關(guān)于該函數(shù)的入口地址就會指向父類的該函數(shù)的代碼入口地址
2015-12-29
父類函數(shù)如果是虛函數(shù),子類的同名函數(shù)(參數(shù)也要相同哦)就一定是虛函數(shù),子類的子類也一樣
父類函數(shù)不是虛函數(shù),子類同名函數(shù)是虛函數(shù),編譯是沒有問題的,如果沒有父類指針指向子類對象的操作也是沒有問題的,但是有父類指針指向子類對象的操作時,操作的函數(shù)會是父類的函數(shù),至此都沒有什么問題,但是在父類的指針釋放內(nèi)存時,系統(tǒng)就會出問題。這時候如果子類還有孫子類,那么子類指針指向?qū)O子類以及重孫子類,都會是覆蓋,也就是調(diào)用同名函數(shù)的時候,執(zhí)行的都是實際對象的函數(shù)實現(xiàn)。但是父類指針指向?qū)O子類以及重孫子類與指向子類的效果是一樣的。這是我 實測的結(jié)果,在delete父類指針時,內(nèi)存無法釋放,系統(tǒng)就出問題了。
我分析了一下,父類函數(shù)不是虛函數(shù),在子類修飾為虛函數(shù),這時候,父類的虛函數(shù)表中指向假設(shè)0x12345內(nèi)存地址,子類的虛函數(shù)表也應(yīng)該是指向0x12345,這樣在實例化類的時候,由于父類中該函數(shù)是非virtual的,子類的指向也不會變,所以執(zhí)行結(jié)果就是父類與子類的該函數(shù)執(zhí)行父類的函數(shù)實現(xiàn)。父類指針指向?qū)O子類的時候,孫子類的虛函數(shù)表由于子類聲明為虛函數(shù),就指向假設(shè)0x67890內(nèi)存地址,由于父類的該函數(shù)是非virtual的,所以孫子類對象的該函數(shù)在虛函數(shù)表中要以父類的地址為準(zhǔn),而不會用0x67890覆蓋掉父類的0x12345,所以執(zhí)行結(jié)果仍是父類的實現(xiàn)。這時候子類指針指向?qū)O子類的時候,就與咱學(xué)的一樣嘍,執(zhí)行結(jié)果是孫子類的實現(xiàn)。
再來說一下釋放內(nèi)存出的問題,具體我還真分析不出來,不過如果父類的析構(gòu)函數(shù)是虛析構(gòu)函數(shù)的話,內(nèi)存的釋放也是沒有問題的,所以我們其它的不管(不管業(yè)務(wù)是否有業(yè)務(wù)需要),析構(gòu)函數(shù)最好都加上virtual關(guān)鍵字。對于如果有可能被繼承的類,其函數(shù)最好都聲明稱虛函數(shù),這樣繼承才有意義,才可以讓你的邏輯在運(yùn)行時決定使用哪個具體實現(xiàn)(多態(tài))。virtual應(yīng)該就是為了實現(xiàn)面向?qū)ο笾械亩鄳B(tài)才誕生的吧
不用不好意思,學(xué)習(xí)哪不會說出來咱們一起討論,吃透了,學(xué)會了才是我們的目的。