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

深度探索 C++ 物件模型 (7):函式語意學與虛函式機制

     編輯:關於C++

前言

繼續研讀《深度探索 C++ 物件模型》第四章:函式語意學。C++ 支援三種成員函式:靜態、虛擬、非靜態。各自呼叫方式與作用不同。本章深入剖析編譯器內部如何實現這些機制。

非靜態成員函式:編譯器視角的轉換

表面上成員函式直接存取資料成員,效率似乎較高。實際上編譯器將其轉換為非成員函式:

  1. 加入 this 指標參數,綁定物件實例。
  2. 將所有非靜態資料成員存取改為 this->member 形式。
  3. 函式名稱經過修飾 (Name Mangling) 確保唯一性 (含類別名、參數列表)。

轉換範例

// 原始成員函式
float Point3d::magnitude() const { ... }

// 編譯器內部偽碼
float magnitude__7Point3dFv(register Point3d* const this) {
    return sqrt(this->_x * this->_x + this->_y * this->_y + this->_z * this->_z);
}

// 呼叫轉換
obj.magnitude();  //  ->  magnitude__7Point3dFv(&obj);

結論:非靜態成員函式與外部函式效率相同 (兩鐵球同時落地)。名稱修飾包含類別名與參數列表保證唯一性。

靜態成員函式:無 this 指標

  • 無 this 指標,不需透過物件呼叫 (可用類別名呼叫)。
  • 無法直接存取非靜態成員。
  • 不可宣告為 virtual, const, volatile。
  • 取得位址為一般函式指標,非成員函式指標。

解決「需存取靜態資料但不想建立物件」的問題,語意接近非成員函式但受類別作用域限制。

虛擬函式:執行期多態的核心

多態概念

以 public base class 指標/參考指向衍生類物件。消極多態:編譯期完成 (如函式多載);積極多態:執行期透過指標/參考查找衍生類物件並呼叫正確實體。

虛擬函式表 (vtable) 機制

  • 每個類別擁有一個虛擬函式表,包含有效虛擬函式位址。
  • 物件建立時含 vptr 指向其類別的 vtable。
  • 衍生類覆寫基類虛擬函式 → vtable 更新為新位址;未覆寫 → 繼承基類位址。
  • 每個虛擬函式在繼承體系中有固定索引值 (slot)。
  • 純虛擬函式槽位填入 pure_virtual_called()。

執行期呼叫流程

ptr->z(); // ptr 為 Base* 指向 Derived 物件
// 1. 透過 ptr->vptr 找到 vtable
// 2. 以 z() 固定索引取得函式位址
// 3. 呼叫該位址 (Derived::z 或 Base::z)

呼叫端不知物件真實型別,只知 vtable 與索引。單一繼承下此機制極高效。判斷類別是否支援多態:檢查是否有虛擬函式。

心得

理解編譯器內部轉換與 vtable 機制,能釐清成員函式效率迷思、靜態與虛擬函式的本質差異,為進階 C++ 開發打下堅實基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved