C++虛函數(shù)

什么是虛函數(shù)

C++中的虛函數(shù)的作用主要是實(shí)現(xiàn)了多態(tài)的機(jī)制。關(guān)于多態(tài)隧土,簡而言之就是用父類型別的指針指向其子類的實(shí)例命爬,然后通過父類的指針調(diào)用實(shí)際子類的成員函數(shù)。這種技術(shù)可以讓父類的指針有“多種形態(tài)”

虛函數(shù)表

虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實(shí)現(xiàn)的皆愉。在這個(gè)表中艇抠,主是要一個(gè)類的虛函數(shù)的地址表,這張表解決了繼承翔脱、覆蓋的問題。這樣届吁,在有虛函數(shù)的類的實(shí)例中這個(gè)表被分配在了這個(gè)實(shí)例的內(nèi)存中绿鸣,所以,當(dāng)我們用父類的指針來操作一個(gè)子類的時(shí)候亮蛔,這張?zhí)摵瘮?shù)表就顯得由為重要了擎厢,它就像一個(gè)地圖一樣,指明了實(shí)際所應(yīng)該調(diào)用的函數(shù)芬探。

C++的編譯器確保虛函數(shù)表的指針存在于對象實(shí)例中最前面的位置(確保虛函數(shù)的性能)厘惦。 這意味著我們通過對象實(shí)例的地址得到這張?zhí)摵瘮?shù)表,然后就可以遍歷其中函數(shù)指針,并調(diào)用相應(yīng)的函數(shù)节榜。

class Base {
            public:
            virtual void f() {  }
            virtual void g() { }
            virtual void h() { }
};
父類虛函數(shù)表

一般繼承(無虛函數(shù)覆蓋)

子類沒有覆蓋父類的虛函數(shù)

在這個(gè)繼承關(guān)系中全跨,子類沒有重載任何父類的函數(shù)亿遂。那么,在派生類的實(shí)例中
1)虛函數(shù)按照其聲明順序放于表中挪钓。

2)父類的虛函數(shù)在子類的虛函數(shù)前面耳舅。

一般繼承(有虛函數(shù)覆蓋)

子類

class Derive:public Base{
     void f();
}
子類覆蓋父類的虛函數(shù)

我們從表中可以看到下面幾點(diǎn),

1)覆蓋的f()函數(shù)被放到了虛表中原來父類虛函數(shù)的位置馏予。

2)沒有被覆蓋的函數(shù)依舊。

這樣霞丧,我們就可以看到對于下面這樣的程序冕香,

            Base *b = new Derive();
            b->f();

由b所指的內(nèi)存中的虛函數(shù)表的f()的位置已經(jīng)被Derive::f()函數(shù)地址所取代,于是在實(shí)際調(diào)用發(fā)生時(shí)突那,是Derive::f()被調(diào)用了构眯。這就實(shí)現(xiàn)了多態(tài)。

多重繼承(無虛函數(shù)覆蓋)

子類的成員函數(shù)被放到了第一個(gè)父類表中

1猫缭、每個(gè)父類都有自己的虛表它褪。
2翘悉、第一個(gè)父類是按照聲明順序來判斷的

多重繼承(有虛函數(shù)覆蓋)

我們在子類中覆蓋了父類的f()函數(shù)。


三個(gè)父類虛函數(shù)表中的f()都被替換

我們可以看見老赤,三個(gè)父類虛函數(shù)表中的f()的位置被替換成了子類的函數(shù)指針。這樣抬旺,我們就可以任一靜態(tài)類型的父類來指向子類,并調(diào)用子類的f()了

虛表的結(jié)尾

windows下以NULL為結(jié)尾
Linux下如果是多重繼承汉柒,則以1結(jié)尾责鳍,0代表沒有后續(xù)的虛表了。

虛函數(shù)的一些問題

1正塌、通過父類型的指針訪問子類自己的虛函數(shù)
任何妄圖使用父類指針想調(diào)用子類中的未覆蓋父類的成員函數(shù)的行為都會被編譯器視為非法,這樣的程序根本無法編譯通過乓诽。但在運(yùn)行時(shí)咒程,我們可以通過指針的方式訪問虛函數(shù)表來達(dá)到違反C++語義的行為。
2粮宛、 訪問non-public的虛函數(shù)
另外,如果父類的虛函數(shù)是private或是protected的巍杈,但這些非public的虛函數(shù)同樣會存在于虛函數(shù)表中扛伍,所以,我們同樣可以使用訪問虛函數(shù)表的方式來訪問這些non-public的虛函數(shù)鳖宾,這是很容易做到的。

虛函數(shù)的效率

虛函數(shù)需要一次間接的尋鼎文。而一般的函數(shù)可以在編譯時(shí)定位到函數(shù)的地址因俐,而虛函數(shù)(動(dòng)態(tài)類型調(diào)用)是根據(jù)某個(gè)指針定位到函數(shù)在虛函數(shù)表的地址周偎。當(dāng)在動(dòng)態(tài)執(zhí)行時(shí)蓉坎,會到該函數(shù)表中尋找函數(shù),多增加了一個(gè)過程蛉艾,效率自然比較低一點(diǎn)衷敌。(虛函數(shù)內(nèi)部執(zhí)行時(shí)間越短,虛函數(shù)查找時(shí)間占比就越高缴罗,相對來說性能損耗就越高)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瞒爬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子侧但,更是在濱河造成了極大的恐慌,老刑警劉巖屁药,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柏锄,死亡現(xiàn)場離奇詭異,居然都是意外死亡缭嫡,警方通過查閱死者的電腦和手機(jī)抬闷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來评架,“玉大人炕泳,你說我怎么就攤上這事∨嘧瘢” “怎么了登刺?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵茁裙,是天一觀的道長节仿。 經(jīng)常有香客問我晤锥,道長廊宪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任壕翩,我火速辦了婚禮傅寡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘荐操。我一直安慰自己,他們只是感情好宅倒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布屯耸。 她就那樣靜靜地躺著,像睡著了一般线召。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灶搜,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天工窍,我揣著相機(jī)與錄音,去河邊找鬼鹏溯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丙挽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播颜阐,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瑰艘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起紫新,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤李剖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后偶芍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匪蟀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年萄窜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撒桨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡穗泵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出佃延,到底是詐尸還是另有隱情,我是刑警寧澤履肃,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布坐桩,位于F島的核電站,受9級特大地震影響膘螟,放射性物質(zhì)發(fā)生泄漏成福。R本人自食惡果不足惜奴艾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一内斯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘿期,春花似錦埋合、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽振诬。三九已至,卻和暖如春肩豁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背清钥。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工放闺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怖侦。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像搬葬,于是被迫代替她去往敵國和親艳悔。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

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

  • 虛函數(shù)表 C++中虛函數(shù)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實(shí)現(xiàn)的香府,在這個(gè)表中董栽,主要是一個(gè)類的虛函數(shù)...
    MrYun閱讀 1,018評論 0 0
  • 參考來源:知乎 定義一個(gè)函數(shù)為虛函數(shù)锭碳,不代表函數(shù)為不被實(shí)現(xiàn)的函數(shù)勿璃。定義他為虛函數(shù)是為了允許用基類的指針來調(diào)用子類的...
    夜幕青雨閱讀 850評論 0 6
  • 什么叫多態(tài)性? A:同樣的消息被不同類型的對象接收時(shí)撵孤,對象會采用完全不同的行為處理消息。 多態(tài)性有幾種邪码? A:靜態(tài)...
    涼拌姨媽好吃閱讀 646評論 0 0
  • 《陸子生香》這是南溪寫的一篇短小說咬清,其實(shí)寫小說,真的對南溪來說也沒什么難的旧烧。這是一篇批判中國社會“重男輕女”的丑陋...
    南溪向南北歌流海閱讀 185評論 0 2
  • 不同程度的路面上積滿了水,每當(dāng)飛馳而過的車子濺起一地雨水時(shí)粪滤,總會伴隨著怒罵聲,有的行人不小心被濺得滿身都是水杖小。 這...
    三兩水閱讀 172評論 0 1