最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談C++ 虛函數

 更新時間:2020年09月14日 15:31:46   作者:bianchengnan  
這篇文章主要介紹了C++ 虛函數的相關資料,幫助大家更好的理解和學習c++,感興趣的朋友可以了解下

緣起

在上一篇文章中,測試代碼2 中的 pBaseA->AA(); 輸出的內容很“奇怪”。其實,完全在情理之中。本文將簡單探究一下 c++ 中的虛函數實現機制。本文主要基于 vs2013 生成的 32 位代碼進行研究,相信其它編譯器(比如,gcc)的實現大同小異。

先從對象大小開始

假設我們有如下代碼,假設 int 占 4 字節(jié),指針占 4 字節(jié)。

#include "stdafx.h"
#include "stdlib.h"
#include "stddef.h"

class CBase
{
public:
  virtual void VFun1() { printf(__FUNCTION__ "\n"); }
  virtual void VFun2() { printf(__FUNCTION__ "\n"); }
  virtual ~CBase() { printf(__FUNCTION__ "\n"); }
  int data;
};

class CDerived : public CBase
{
public:
  virtual void VFunNew() { printf(__FUNCTION__ "\n"); }
  virtual void VFun1() override { printf(__FUNCTION__ "\n"); }
  virtual ~CDerived() override { printf(__FUNCTION__ "\n"); }
};

int _tmain(int argc, _TCHAR* argv[])
{
  printf("sizeof CBase is: %d, offset of data is %d\n",
      sizeof(CBase), offsetof(CBase, data));
  system("pause");

  CBase* pBase = new CDerived();
  pBase->VFun1();
  pBase->VFun2();
  system("pause");
  return 0;
}

輸出結果如下圖:

有沒有覺得意外?從類定義可知,data 占 4 字節(jié),那另外的 4 字節(jié)是哪里來的呢?data 的偏移值不應該是 0 嗎?為什么是 4 呢?

內存布局

如果一個類有虛函數,編譯器會自動為這個類型的對象在頭部增加一個虛表指針(vftable),指向虛函數表。虛函數表中存放著一個個的虛函數。

CBaseCDerived 類對象的內存布局如下:

注意:虛函數表中索引為 -1 的地方指向了跟動態(tài)類型轉換相關的信息。

虛表指針的初始化

vftable 是在類的構造函數中初始化的??梢栽?code> IDA 中分別查看 CBase 類 和 CDerived 類的構造函數的反匯編代碼。

CBase 構造函數的反匯編代碼如下(關鍵部分已注釋):

由反匯編代碼可知, CBase 的構造函數會把 CBase 對象開始的位置(存放虛表指針)設置為 CBase::vftable。

CDerived 構造函數的反匯編代碼如下(關鍵部分已注釋):

由反匯編代碼可知, CDerived 的構造函數會先調用 CBase 的構造函數進行基類部分的初始化,在 CBase 構造函數的內部把 CDerived 對象開始的位置設置為 CBase::vftable,然后調用自身的初始化部分,會把 CDerived::vftable 的地址放到對象開始的位置,從而替換掉了 CBase 類的虛表指針。

虛函數表的內容

了解完了虛表指針的初始化過程,再來看看 vftable 里面都有哪些內容。

可以雙擊 ??_7CBase@@6B@ (或者直接按回車)跳轉到虛表所在的地方。如下圖:

說明:上側是 CBase 類的虛表內容,下側是 CDerived 類的虛表內容。

請注意圖片上側黃色高亮部分,也就是 vftable[-1] 的地方,是跟動態(tài)類型轉換相關的信息,后面有機會介紹。

虛函數調用

理解了類對象的內存布局及虛函數表之后,再理解虛函數的調用過程就比較簡單了。

有些 C++ 基礎的小伙伴兒都知道本例中的輸出結果應該如下圖所示:

直接看一下 pBase->VFun1() pBase->VFun2() 對應的反匯編代碼就應該明白一切了。如下圖:

因為 pBase 指向的實際是 CDerived 類型的對象,所以虛表是 CDerived 類的。如下圖所示

經過以上的分析,輸出結果合情合理。

說明

本文只是拿了一個最最簡單的例子做演示。像多重繼承,虛繼承等比較復雜的情況,感興趣的小伙伴可以自行研究。

雖然這個例子很簡單,但是背后的機理值得了解清楚,非常有用。比如,當庫中的接口與庫頭文件不匹配的時候,很可能莫名其妙的就崩潰了。這時可以通過查看指針對應的虛表的內容來查看庫中的虛函數都有哪些,跟頭文件對比后就可以比較準確的判斷是否是庫不匹配的問題。還可以根據虛表的內容,猜測出基類指針指向的具體的子類對象的類型。

可以在 windbg 中使用 dps 命令快速打印,如下圖:

總結

  • 虛表指針是在類的構造函數中初始化的,相應的代碼由編譯器自動生成。
  • 在生成調用虛函數的代碼的時候,并沒有直接把虛函數地址寫死,而是通過虛表進行調用,多了一層間接層。
  • Any problem in computer science can be solved by anther layer of indirection. (計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決)

注意:如果通過對象調用虛函數,會是另外一種情況,因為不存在多態(tài),直接使用函數低級進行調用就可以了。感興趣的小伙伴兒可以自行實驗。

參考資料

深度探索 c++ 對象模型

以上就是淺談C++ 虛函數的詳細內容,更多關于C++ 虛函數的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解C++ 模板編程

    詳解C++ 模板編程

    模板(template)是C++實現泛型(Generics)和元編程(Meta Programming)的基礎。本文拋磚引玉,簡要介紹C++模板編程,不足之處敬請指正。
    2020-09-09
  • OpenCV實現圖像去噪算法的步驟詳解

    OpenCV實現圖像去噪算法的步驟詳解

    這篇文章主要為大家介紹了OpenCV中圖像去噪算法的原理,文中通過示例為大家詳細講解了圖像去噪算法的使用,感興趣的小伙伴可以了解一下
    2022-06-06
  • 手把手教你如何一眼分辨是C還是C++

    手把手教你如何一眼分辨是C還是C++

    在很大程度上,C++是C的超集,這意味著一個有效的C程序也是一個有效的C++程序,下面這篇文章主要給大家介紹了關于如何一眼分辨是C還是C++的相關資料,需要的朋友可以參考下
    2023-02-02
  • 深入探討C++父類子類中虛函數的應用

    深入探討C++父類子類中虛函數的應用

    本篇文章是對C++父類子類中虛函數的使用進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++?如何將Lambda轉換成函數指針

    C++?如何將Lambda轉換成函數指針

    這篇文章主要介紹了C++?如何將Lambda轉換成函數指針,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++實現超市商品管理系統(tǒng)最新版

    C++實現超市商品管理系統(tǒng)最新版

    這篇文章主要為大家詳細介紹了C++實現超市商品管理系統(tǒng)最新版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 帶你了解C++的數組與函數

    帶你了解C++的數組與函數

    這篇文章主要介紹了C++的數組與函數,包括數組的初始化等基本知識,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • C語言中.與->的用法介紹

    C語言中.與->的用法介紹

    結構體用點,結構體指針用箭頭,簡單的說,就是一個快捷方式,一個語法糖,這篇文章主要介紹了C語言中.與->的區(qū)別及用法,需要的朋友可以參考下
    2023-05-05
  • C++核心編程之占位參數和默認參數

    C++核心編程之占位參數和默認參數

    這篇文章主要介紹了C++核心編程之占位參數和默認參數,c++中函數的形參列表中的形參是可以有默認值的,函數的形參列表里可以有占位參數,用來占位,調用函數時必須填補位置。下面更多相關內容的詳細介紹,需要的小伙伴可以參考一下
    2022-03-03
  • C語言目標文件的詳細講解

    C語言目標文件的詳細講解

    最近正在閱讀關于C語言的庫,但是我還沒有find關于目標文件的解釋,這篇文章主要給大家介紹了C語言目標文件的詳細講解,文中介紹的非常詳細,需要的朋友可以參考下
    2023-01-01

最新評論

灵丘县| 临夏县| 四会市| 横山县| 柏乡县| 措勤县| 北流市| 益阳市| 雷州市| 崇左市| 平遥县| 上蔡县| 滁州市| 青龙| 扶沟县| 金阳县| 海伦市| 通榆县| 邹平县| 玉林市| 禹城市| 永寿县| 静安区| 镇平县| 留坝县| 通州区| 昌吉市| 丽水市| 桓台县| 凌云县| 武平县| 巴彦淖尔市| 巴彦县| 桂林市| 剑河县| 石泉县| 宜宾县| 陆川县| 法库县| 闻喜县| 云浮市|