在 COM 開發中,手動管理引用計數(AddRef/Release)既繁瑣又容易出錯。ATL 提供的智能指針模板類 CComPtr 和 CComQIPtr 能夠自動處理引用計數,極大地簡化了代碼並提高了安全性。本文通過一個實例 ComTest 組件(實現 ICmd 和 IStr 兩個接口)演示三種常見的智能指針用法。
#include <atlbase.h>
#include <atlcom.h>
// 方法一、二使用的頭文件
#include "ComTest_i.c"
#include "ComTest.h"
// 方法三使用 #import 導入類型庫
// #import "ComTest.tlb" no_namespace
#include <stdio.h>
#include <stdlib.h>
using namespace ATL;
最基礎的用法:先創建 IUnknown,再通過 QueryInterface 獲取具體接口指針。
CComPtr<IUnknown> pUnk;
CComQIPtr<ICmd> pCmd;
HRESULT hr;
hr = pUnk.CoCreateInstance(CLSID_Cmd, NULL, CLSCTX_INPROC);
hr = pUnk.QueryInterface(&pCmd); // 等同於創建 ICmd 對象
int sum;
hr = pCmd->Add(1, 2, &sum);
printf("%d\n", sum);
// 智能指針會自動 Release,但顯式調用也無妨
pUnk.Release();
pCmd.Release();
利用 CComQIPtr 的賦值運算符重載,自動完成 QueryInterface,代碼更簡潔,且能輕鬆獲取多個接口。
CComPtr<IUnknown> pUnk;
pUnk.CoCreateInstance(CLSID_Cmd, NULL, CLSCTX_INPROC);
CComQIPtr<ICmd> pCmd = pUnk; // 自動 QI
CComQIPtr<IStr> pStr = pUnk; // 同一對象獲取另一接口
int sum;
pCmd->Add(1, 2, &sum);
printf("%d\n", sum);
CComBSTR bstr;
pStr->Cat((BSTR)"d", (BSTR)"e", &bstr);
printf("%S\n", bstr);
// 離開作用域自動 Release,顯式調用亦可
pStr.Release();
pCmd.Release();
pUnk.Release();
#import 會生成帶有 Ptr 後綴的智能指針類型(如 ICmdPtr),用法類似 ADO,適合快速原型開發。
// 需取消註釋 #import 行
ICmdPtr cmd = NULL;
cmd.CreateInstance(__uuidof(Cmd));
int sum;
cmd->Add(1, 2, &sum);
printf("%d\n", sum);
cmd.Release(); // 必須顯式釋放
Release,防止內存洩漏。CComQIPtr 的賦值操作封裝了 QueryInterface,比手動調用更安全。HRESULT 返回值,生產代碼中不可忽略。本文出自 “Studoc” 博客,原文地址:https://studoc.blog.51cto.com/1284909/282721