C++虛函數學習筆記(僅供參考)

1、虛函數的作用:
允許在派生類中重新定義與基類同名的函數,並且可以通過基類的指針或引用來訪問基類和派生類中的同名函數。

2、虛函數的工作原理
編譯器處理虛函數的方法:對每個對象添加一個隱藏成員。
隱藏成員中保存了一個指向函數地址數組的指針,這種數組稱爲虛函數表(vtbl)。虛函數表中存儲了爲類對象進行聲明的虛函數的地址。
例如:基類對象包含一個指針,該指針指向基類中所有虛函數的地址表。派生類對象將包含一個指向獨立地址表的指針如果派生類提供了虛函數的新定義

,該虛函數表將保存新函數的地址,如果沒有重新定義虛函數該vtbl將保存函數原始版本的地址,如果派生類定義了新的虛函數,則該函數的地址也將被

添加到vtbl中。
注:無論類中包含了多少虛函數,都只需在對象中添加一個地址成員,只是表的大小不同。

C++規定:當一個成員函數聲明爲基類後,其派生類中的同名函數也自動成爲虛函數。

虛函數使用的注意事項:
一、只能用virtual聲明類的成員函數,使它成爲虛函數,而不能將類外的普通函數聲明爲虛函數,因爲虛函數的作用是允許在派生類中對基類的虛函數

重新定義。顯然,它只能用於類的繼承層次結構中。
二、一個成員函數被聲明爲虛函數後,在同一類族中的類就不能再定義一個非virtual的但與該虛函數具有相同參數的(包括個數和類型)和函數返回值

類型的同名函數。


靜態關聯與動態關聯:
關聯:確定調用具體對象的過程稱爲關聯。
靜態關聯:函數重載和通過對象名調用的虛函數,在編譯時可確定其調用的虛函數屬於哪一個類,其過程稱爲靜態關聯;
動態關聯:在運行階段將類和對象綁定在一起的過程稱爲動態關聯;如:在虛函數中的pt->display(),無法確定確定應調用哪一類的虛函數,在這樣的情

況下,編譯系統把它放到運行階段處理,在運行階段確定其關聯關係。在運行階段,基類指針變量先指向某一個類的對象,然後通過此指針變量調用該對

象中的函數,此時調用哪一個對象的函數就確定了。

注:編譯只做靜態的語法檢查,故自從語句的形式是無法確定調用對象的。


什麼爲虛函數時的依據:
一、首先看成員函數是否會作爲基類。然後看成員函數在類的繼承後有無可能被更改功能,如果希望更改其功能的,一般應該將它聲明爲虛函數。
二、如果成員函數在類被繼承後功能不許修改,或派生類用不到該函數,則不要將它聲明爲虛函數。不要僅考慮到作爲基類而把類中的所有成員函數都聲

明爲虛函數。
三、應考慮對成員函數的調用是通過對象名還是通過基類指針或引用去訪問,如果是通過基類指針或引用去訪問的,則應當聲明爲虛函數。
四、有時,再定義虛函數時,並不定義其函數體,即函數體是空的。它的作用只是定義了一個虛函數名,具體功能留給派生類去添加。


注意:使用虛函數時,系統要有一定的空間開銷。當一個類帶有虛函數時,編譯器會爲該類構造一個虛函數表,它是一個指針數組,存放每個虛函數的入

口地址。系統進行動態關聯時的時間開銷是很少的,因此多態性是高效的。

虛析構函數:
普通析構函數:系統只會執行基類的析構函數,而不執行派生類的析構函數;
虛析構函數:將析構函數聲明爲虛函數,由該基類派生出的所有的派生類的虛構函數也自動成爲虛函數,使之執行所有派生類的析構函數(即使派生類的

析構函數與基類的析構函數名字不相同)。
注:在程序中,最好把基類的析構函數聲明爲虛函數。
程序員一般都習慣聲明虛析構函數,即使基類不需要析構函數,也顯示的定義一個函數體爲空的虛析構函數,以保證撤銷動態存儲空間時能得到正確的處

理。


注:構造函數不能聲明爲虛函數,因爲在執行構造函數時類對象還未完成建立過程,當然談不上函數與類的關聯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章