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

ATL CComPtr 深度解析:極簡主義下的高效 COM 智能指標實踐

     編輯:關於C語言

條款 4:理解 ATL CComPtr——極簡、高效的設計哲學

微軟發布 COM SDK 後很快意識到直接用 SDK 開發 COM 太難,首嘗試將 COM 整合進 MFC。但隨網際網路發展,分散式組件需在網路上傳輸,MFC 的臃腫、龐大與大量 DLL 依賴成了阻礙——ATL (ActiveX Template Library) 應運而生。

不同於 MFC,ATL 採用多重繼承與模板這兩大 C++ 進階技巧,讓開發者能快速產出高效、精簡的程式碼,編出的組件更輕量小巧。代價是學習曲線較陡峭。

CComPtr:為解決引用計數而生的類模板

CComPtr 是 ATL 為自動管理 COM 介面引用計數提供的類模板。智能指標需透過模板實現(多數為通用性考量),所以「智能指標」本質上是特定模板的通俗別名——不會因使用模板等高階技巧而產生高不可攀感,且行為更貼近介面指標。

ATL 另提供 CComQIPtr,兩者皆繼承自 CComPtrBase,差異在於 CComQIPtr 能在必要時自動查詢介面(如賦值不同參數化型別指標時自動 QueryInterface)。CComPtrBase 封裝了公共函數實現碼復用。繼承關係如下:

CComPtr/CComQIPtr/CComPtrBase 繼承關係圖

注意:舊版 VC(如 VC6.0)無 CComQIPtr 與 CComPtrBase,僅有孤單的 CComPtr。後期為擴充功能才抽出基類。本文僅討論 CComPtr 及 CComPtrBase。

CComPtr 使用範例與核心規則

以 IHello* 為例,程式中所有介面指標型別(參數除外)皆以 CComPtr<IHello> 取代:

void SomeApp(IHello* pHello) {
    CComPtr<IHello> pCopy = pHello;
    OtherApp();
    pCopy->Hello();
}

四大必守鐵律:

  1. CComPtr 已保證 AddRef/Release 正確呼叫,不可再手動呼叫;
  2. 釋放智能指標:直接賦 NULL 值;
  3. CComPtr 析構時自動釋放 COM 指標;
  4. 使用 & 運算符(取指標位址)時,必須確保智能指標為 NULL(否則前指標無法釋放,CComPtr 會 assert 報警)。

ATL 極簡哲學:恰到好處,拒絕過度設計

ATL 追求簡潔高效,解決問題採用一種方法即可(除非確有不同必要)。從建構函數可見一斑:僅 4 個——必要的預設/拷貝建構函數,加 2 個為滿足指標語法的轉換建構函數,「恰當好處」就夠了。組件建立、介面查詢等,ATL 認為透過建構後的智能指標完成即可:

CComPtr<ICalculator> spCalculator = NULL;
hrRetCode = spCalculator.CoCreateInstance(CLSID_CALCULATOR);
KG_COM_ASSERT_EXIT(hrRetCode);
hrRetCode = spCalculator->Add(1, 2, &nSum);

雖看似未滿足 RAII(資源與管理物件同生命週期),實則滿足——RAII 僅要求資源獲取處即與管理物件綁定。ATL 認為這樣最夠、程式碼最清晰簡單。

賦值運算符亦未做自動介面查詢(後續版本部分加入)。ATL 認為有 QueryInterface,開發者自能完成查詢:

ICalculator* pCalculator = NULL;
CComPtr<IUnknown> spIUnknown = NULL;
hrRetCode = spIUnknown.CoCreateInstance(CLSID_CALCULATOR);
KG_COM_ASSERT_EXIT(hrRetCode);
hrRetCode = spIUnknown.QueryInterface(&pCalculator); // 手動查詢
KG_COM_ASSERT_EXIT(hrRetCode);
hrRetCode = pCalculator->Add(1, 2, &nSum);

問題解決,完美詮釋 ATL 哲學:簡單!高效! 自動查詢介面的便利與危機,詳見條款 26。

—— 作者:liuchang5 的專欄

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