文章目錄
- 1、虛函數表指針
- 2、多態構成的條件
- 3、重載、重寫、重定義 三者區別
- 4、繼承與虛函數
- 5、單繼承中的虛函數表
- 無虛函數覆蓋
- 有虛函數覆蓋
- 6、單繼承中的虛函數表
- 無虛函數覆蓋
- 有虛函數覆蓋
- 參考
看《深度探索c++對象模型》的時候對虛表有了點疑惑,正好網上有些文章解除了這個疑惑,記錄一下
1、虛函數表指針
在64位操作系統下當我們計算包含虛函數的類大小時,我們會發現不管類中有幾個虛函數,類的大小都會比沒有虛函數時類的大小大8,這是因為存了一個指向虛表的指針,大小為8字節。
對象中的這個指針我們叫做虛函數表指針,虛函數指針指向的這個表叫虛函數表簡稱虛表,虛表中存的是虛函數的地址
![]() | ![]() |
2、多態構成的條件
- 必須通過父類的指針或者引用調用虛函數
- 父類的函數必須是虛函數,且子類必須對父類的虛函數進行重寫
3、重載、重寫、重定義 三者區別
4、繼承與虛函數
在構造子類前會先構造父類,而在構造父類的時候,通過this指針看到如下圖左所示,虛函數表中存的父類中的三個虛函數的地址,而在構造子類的時候,可以看到如下圖右所示,父類中的虛函數在子類中被重寫的兩個虛函數將父類的虛函數覆蓋了,這就是多態父類指針保存子類地址卻可以通過父類指針訪問子類成員的原因
當我們在子類中對父類的虛函數重寫后,當父類去調用該虛函數的時候,就會訪問虛表,然而虛表中存放的是已經被子類覆蓋的子類的函數,所以就會轉去調用子類中的重寫的虛函數。
其實子類的虛函數是在虛表中的,只不過從監視器的角度看不到,因為從監視器的角度__vfptr的成員始終屬于父類的成員。
5、單繼承中的虛函數表
無虛函數覆蓋
虛函數按照其聲明順序放于表中;
父類的虛函數在子類的虛函數前面;
有虛函數覆蓋
覆蓋的fun1()函數被放到了虛函數表中原來父類虛函數的位置
沒被覆蓋的函數依舊
6、單繼承中的虛函數表
無虛函數覆蓋
每個父類都有自己的虛表
子類的成員函數被放到第一個父類的表中(所謂第一個父類是按照聲明順序來判斷的)------>這樣做是為了解決不同的父類類型的指針指向同一個子類實例,而能夠調用到實際的函數
子類實例中的虛函數表如下圖所示:
有虛函數覆蓋
只要子類中重寫的父類的虛函數都會覆蓋
沒被覆蓋的函數依舊
子類虛函數表如下:
參考
https://blog.csdn.net/weixin_50886514/article/details/117536971
https://bbs.csdn.net/topics/370154900?page=3