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

COM 原理與應用:COM 物件與介面核心概念

     編輯:關於C++

COM 物件理解

COM 物件類似 C++ 類別實例,封裝狀態(屬性)與行為(方法)。關鍵差異:

COM 物件標識:CLSID / GUID

  • GUID:128 位全域唯一識別碼,由網卡位址(空間值)與時間戳(時間值)生成,重複機率極低。
  • 工具:GUIDGen.exe、UUIDGen.exe、API CoCreateGuid()。
  • CLSID:類別 ID,註冊表 HKEY_CLASSES_ROOT\CLSID 下以 GUID 命名。

COM 介面核心

介面定義與 vtable

  • 介面 = 一組函數的虛函數表指標 (vtable pointer) 集合。
  • 用戶端持有介面指標 pInterface,實際指向 pVtable,再指向函數指標陣列。
  • 呼叫慣例:__stdcall(Callee 清理堆疊,跨語言相容)。
  • 參數:字串必須用 Unicode (BSTR/OLECHAR)。

C/C++ 定義介面

// C 風格:需顯式 this 指標
typedef struct IMyInterface {
    void (__stdcall *Method1)(IMyInterface* this, int arg);
    HRESULT (__stdcall *Method2)(IMyInterface* this, BSTR* pOut);
} IMyInterface;

// C++ 風格:類別隱含 this,vtable 結構天然相容
class IMyInterface {
public:
    virtual void __stdcall Method1(int arg) = 0;
    virtual HRESULT __stdcall Method2(BSTR* pOut) = 0;
};
C++ class 定義介面最直觀,編譯器自動產生符合 COM 規範的 vtable 結構。

介面與物件的關聯

物件實作介面,需將介面指標暴露給客戶端。實作方式:

  • 多重繼承:物件類別繼承所有介面類別,直接實作虛擬函式。
  • 內嵌介面類別成員:物件包含介面實作類別實例,透過 this 調整指標回傳介面。
  • MFC/ATL 採用不同機制連接介面指標與物件資料。

介面描述語言 IDL

  • 平台無關、語言中立的介面定義語言(基於 DCE IDL 擴展)。
  • 定義介面、方法、參數屬性、自訂資料結構、可變長度陣列。
  • MIDL 編譯器產生 .h、_i.c (GUID)、_p.c (Proxy/Stub)、dlldata.c。

介面特性

  1. 二進制相容:跨語言、跨編譯器、跨進程/機器。
  2. 介面不變性:一旦發布不可修改(新功能新增介面,如 IInterface2、IInterfaceEx)。
  3. 繼承性(單繼承):所有介面直接/間接繼承 IUnknown。介面繼承僅繼承「宣告」,不繼承「實作」。
  4. 多型性:透過 QueryInterface 在執行期發現並使用不同介面。

IUnknown:COM 的基石

interface IUnknown {
    HRESULT QueryInterface(REFIID riid, void** ppvObject); // 介面查詢
    ULONG AddRef();  // 參考計數 +1
    ULONG Release(); // 參考計數 -1,歸零時銷毀物件
};
  • 生命週期控制:參考計數機制。
  • 介面查詢:執行期發現物件支援的介面。

參考計數實作層級選擇

  • 組件層級(全域變數):粒度太粗。
  • 物件層級(C++ 成員變數):最適合,精確控制單一物件生命週期。
  • 介面層級(類別成員變數):粒度太細,管理複雜。

參考計數規則速查

特性COM 物件C++ 物件
封裝性二進制層級完全封裝,僅透過介面存取語義層級封裝(public/private)
重用機制包容與聚合繼承
多型機制介面查詢虛擬函式
標識CLSID (GUID)型別名稱

介面查詢規範

  • QueryInterface 回傳:S_OK、E_NOINTERFACE、E_UNEXPECTED。
  • 原則:同一物件的所有介面查詢 IUnknown 應回傳同一指標;對稱性、自反性、傳遞性、時間無關性。

多介面物件實作

  • C++ 多重繼承:class Obj : public IFace1, public IFace2,需處理 this 指標調整(QueryInterface 回傳正確介面位址)。
  • 內嵌介面實作類:物件包含實作類實例,QueryInterface 回傳內嵌實例位址。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
情境規則
函數輸入參數 (in)呼叫端負責有效性,被呼叫端不增減計數
函數輸出參數 (out)被呼叫端回傳前 AddRef;同樣適用於介面指標回傳值
輸入輸出參數 (in/out)修改前 Release 舊值,修改後 AddRef 新值
區域介面指標作用域內有效,無需增減
全域/成員介面指標傳遞前 AddRef,用畢 Release(防止他處釋放)
一般賦值賦值後 AddRef 新值;賦值前若舊值仍存活 Release 舊值
結束使用Release