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

深入剖析 static 在 MFC 核心機制中的應用——以訊息映射為例

     編輯:VC 教學

前言

C++ 中的 static 資料成員屬於類別而非物件,所有實例共享同一份拷貝。這特性不僅可實作計數器,更是 MFC 核心機制(動態建立、執行期型別識別、訊息映射、命令傳遞)的基石。本文以《深入淺出 MFC》為藍本,深度解析 static 在訊息映射中的關鍵角色。

static 成員的本質:編譯期即存在

關鍵觀念:**static 成員變數不依賴物件實例化而存在,可視為「有作用域限制的全域變數」**。在進入 AfxWinMain 之前,MFC 核心類別(CWinApp、CWnd、CFrameWnd 等)的 static 成員已完成初始化,構成了訊息傳遞的靜態網狀結構。

DECLARE_MESSAGE_MAP 宏展開

#define DECLARE_MESSAGE_MAP() \
    static AFX_MSGMAP_ENTRY _messageEntries[]; \
    static AFX_MSGMAP messageMap; \
    virtual AFX_MSGMAP* GetMessageMap() const;

當類別 CMyWnd : public CFrameWnd 使用此宏時,實際宣告了:

  • 靜態陣列 _messageEntries[]:儲存該類別的訊息條目
  • 靜態結構 messageMap:指向條目陣列與基類映射表
  • 虛擬函式 GetMessageMap():執行期回傳映射表指標

BEGIN_MESSAGE_MAP 實作映射內容

// MyApp.cpp
BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)
    ON_WM_PAINT()
END_MESSAGE_MAP()

此宏在 **cpp 檔** 中 **定義** 並 **初始化** 兩個 static 成員:

  • CMyWnd::_messageEntries[] = { WM_PAINT 對應處理函式, 結束標記 }
  • CMyWnd::messageMap = { _messageEntries, &CFrameWnd::messageMap }

訊息映射網的建立時機

**關鍵點**:這兩個 static 變數在 **程式啟動、全域物件建構階段** 就已存在,完全 **不需要建立 CMyWnd 物件**。MFC 啟動流程:

  1. 全域/靜態物件建構(含所有類別的 messageMap、_messageEntries)
  2. 進入 AfxWinMain
  3. 建立 CWinApp 衍生物件、主視窗等

因此,訊息路由表在第一個視窗建立前已就緒,佔用固定記憶體,換取極快的訊息分派速度。

為何不用虛擬函數表?

  • 虛擬函數需建立物件才能透過 vptr 存取
  • 訊息映射需支援 **動態掛載/卸載**、**命令目標鏈路由** 等靈活機制
  • static 陣列 + 基類指標鏈,實現「類別級」的靜態繼承關係,避免物件級的虛函數開銷

總結

MFC 巧妙運用 static 的「編譯期存在、類別級共享」特性,在無物件時建立完整的訊息映射網。這不僅是技巧,更是框架設計權衡 **效能、靈活度、記憶體** 的經典案例。理解此機制,有助於深入掌握 MFC 訊息路由、命令傳遞與執行期型別識別的本質。

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