當前位置:
首頁 >
c++远征之多态篇——虚函数及其实现原理
發布時間:2023/12/20
34
豆豆
生活随笔
收集整理的這篇文章主要介紹了
c++远征之多态篇——虚函数及其实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
以下內容源于慕課網的學習整理,如有侵權,請告知刪除。
?1、多態的定義
- 簡單理解,就是對于同一條命令,不同對象會做出不同的操作。
- 相同對象收到不同消息,或者不同對象收到相同消息時,產生不同的動作。
2、多態的分類
(1)靜態多態(早綁定)
- 如函數重載,在編譯階段,(根據傳參情況)就已經知道要執行哪個函數。
(2)動態多態(晚綁定)
a、虛函數
多態具體到語法上是
- 父類和多個子類有同名函數;
- 定義了父類指針并指向了子類對象,然后通過父類指針,調用子類中的同名函數,而非父類中的同名函數。
- 動態多態,即父類調用子類的實現方式。
實現多態,需要將父類中的同名函數定義為虛函數
- 虛函數,即在成員函數前(如析構函數前、普通成員函數前)添加關鍵字virtual。
?下面不是動態多態,因為main中調用的都是父類中的函數
? ? ?
? ? ?
為了實現調用子類中的同名函數,需要在父類的同名函數前添加關鍵字virtual,(建議在子類的同名函數前也添加virtual,但不是必須的)
b、虛析構函數
多態中存在的問題是內存泄漏問題,解決方法是虛析構函數。
- 使用父類指針,去銷毀子類對象時,會出現內存泄漏的問題。
- 因為delet p(p是父類指針)時,執行的是父類的析構函數;
- 而我們希望執行的是子類的析構函數。
- 解決這個問題的方法是,在父類的析構函數前添加virtual,即虛析構函數。
- 實際上,執行完子類的虛析構函數就會執行父類的析構函數。
c、virtual在函數中的使用限制
- 普通函數不能是虛函數,必須是類的成員函數;
- 靜態成員函數不能是虛函數,如 virtual stact int getCount() 是錯誤的;
- 內聯函數不能是虛函數;
- 構造函數不能是虛函數。
3、虛函數和虛析構函數的實現原理
(1)首先知道函數指針這個概念。
(2)虛函數表
- 當父類有虛函數時,并且實例化一個父類對象時,會有一個虛函數表指針,指向了一個虛函數表。
- 通過虛函數表得到虛函數指針,從而得到虛函數的入口地址。
? ?
- 子類也有一個虛函數表,子類的虛函數表的首地址,一般和父類虛函數表的首地址不一樣;
- 假如子類中沒有定義和父類同名的虛函數(如下),那么子類從父類中繼承了虛函數,因此子類的虛函數表中的虛函數指針指向同一個虛函數入口。
- 假如子類中定義了和父類同名的虛函數(如下),那么子類的虛函數將覆蓋父類的虛函數。
(3)虛析構函數的實現原理
- 前提(已知),執行完子類的虛析構函數就會自動執行父類的析構函數。
- 子類中有虛析構函數(如果父類的析構函數用virtual修飾的話,則子類的虛構函數無論是否用virtual修飾,都是虛析構函數);
- 父類指針通過子類的虛函數表指針,得到虛析構函數的入口地址,執行完子類的虛析構函數后,會自動執行父類的析構函數。
(4)證明虛函數表指針的存在?
(5)細節
- 在c++中,多態的實現是通過虛函數表實現的;
- 每個類只有一份虛函數表,所有該類的對象共用同一張虛函數表;
- 兩張函數表中的函數指針可能指向同一個函數。
總結
以上是生活随笔為你收集整理的c++远征之多态篇——虚函数及其实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 查看java/jdk版本
- 下一篇: 修改devcpp5.11的语言选项