首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 對象佈局與多態實現:成員函數調用的底層機制

     編輯:關於C++

引言

本文通過觀察編譯器生成的匯編代碼,分析普通成員函數、靜態成員函數以及指針調用成員函數的底層實現,為後續探討虛函數、虛繼承奠定基礎。

實驗代碼

C010 obj;
PRINT_OBJ_ADR(obj)
obj.foo(); // 對象調用普通成員函數
C012::sfoo(); // 靜態成員函數調用
C010 * pt = &obj;
pt->foo(); // 指針調用普通成員函數

對象調用普通成員函數

匯編:

00422E09 lea ecx,[ebp+FFFFF967h] ; 載入對象地址到 ecx (this指針)
00422E0F call 0041E289 ; 直接調用固定地址 (靜態綁定)

進入函數體:

01 push ebp
02 mov ebp,esp
...
07 push ecx ; 保存 this 指針
...
12 pop ecx ; 彈出 this 到 ecx
13 mov dword ptr [ebp-8],ecx ; 存入局部變量 (this)
14 mov eax,dword ptr [ebp-8]
15 mov byte ptr [eax],2 ; 通過 this 修改成員變量 (偏移 0)

關鍵點:VC7.1 使用 ecx 傳遞 this 指針(而非棧傳遞),函數入口將 ecx 保存至棧帧局部變量區,後續通過該局部變量訪問成員。

靜態成員函數調用

00422E14 call 0041DD84

極其簡單:無 this 指針處理,直接調用固定地址。

指針調用普通成員函數

00422E25 mov ecx,dword ptr [ebp+FFFFF958h] ; 解引用指針獲取對象地址
00422E2B call 0041E289 ; 同樣直接調用

與對象調用幾乎相同,差別在於獲取 this 的方式:對象直接取地址,指針需先解引用。

小結

  • 普通成員函數調用(無論對象或指針)均為靜態綁定,編譯期確定函數地址。
  • this 指針通過 ecx 寄存器傳遞(Microsoft x86 calling convention)。
  • 靜態成員函數無 this,調用開銷最小。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved