共用方式為


如何:建立和使用 CComPtr 和 CComQIPtr 執行個體

在傳統的 Windows 程式設計,程式庫通常是實作為 COM 物件 (或更明確地說,為 COM 伺服器)。 許多 Windows 作業系統元件會實作為 COM 伺服器,因此,許多參與者提供這種形式的程式庫。 如需有關基礎 COM 的資訊,請參閱 Component Object Model (COM)

當您具現化元件物件模型 (COM) 物件時,請將介面指標存放於 COM 智慧型指標,它使用 AddRefRelease 呼叫在解構函式執行參考計算。 如果您使用 Active Template Library (ATL) 或 MFC 程式庫,則使用 CComPtr 智慧型指標。 如果您不使用 ATL 或 MFC,則使用 _com_ptr_t。 由於沒有 COM 相當於 std::unique_ptr,為單一擁有者和多擁有者案例中使用這些智慧型指標。 CComPtrComQIPtr 對有右值的參考支援 MOVE 作業。

範例

下列範例示範如何使用 CComPtr 以具現化 COM 物件和取得本身的介面的指標。 請注意 CComPtr::CoCreateInstance 成員函式用以建立 COM 物件,而不是有相同名稱的 Win32 函式。

void CComPtrDemo()
{

    HRESULT hr = CoInitialize(NULL);

    // Declare the smart pointer.
    CComPtr<IGraphBuilder> pGraph;

    // Use its member function CoCreateInstance to 
    // create the COM object and obtain the IGraphBuilder pointer.
    hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Use the overloaded -> operator to call the interface methods.
    hr = pGraph->RenderFile(L"C:\\Users\\Public\\Music\\Sample Music\\Sleep Away.mp3", NULL);
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Declare a second smart pointer and use it to  
    // obtain another interface from the object.
    CComPtr<IMediaControl> pControl;
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Obtain a third interface.
    CComPtr<IMediaEvent> pEvent;
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Use the second interface.
    hr = pControl->Run();
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Use the third interface. 
    long evCode = 0;
    pEvent->WaitForCompletion(INFINITE, &evCode);

    CoUninitialize();

    // Let the smart pointers do all reference counting.
}

CComPtr 及其家族是 ATL 的一部分且已定義在 atlcomcli.h。 _com_ptr_t 在 comip.h 宣告。 當它產生型別程式庫的包裝函式類別時,編譯器建立特製化的 _com_ptr_t

ATL 也提供 CComQIPtr,具有查詢 COM 物件以擷取其他介面的更簡單的語法。 然而,建議使用 CComPtr ,因為它做 CComQIPtr 可以做的一切並與原始 COM 介面指標更加一致。 如果您使用 CComPtr 查詢介面,新介面指標在 out 參數中。 如果呼叫失敗,傳回 HRESULT,這是一般的 COM 樣式。 用 CComQIPtr,傳回值是指標本身,而且如果呼叫失敗,無法存取內部 HRESULT 傳回值。 下列兩行顯示 CComPtrCComQIPtr 的錯誤處理機制之間的差異。

// CComPtr with error handling:
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }

// CComQIPtr with error handling
CComQIPtr<IMediaEvent> pEvent = pControl;
if(!pEvent){ /*... handle NULL pointer error*/ }

// Use the second interface.
hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }

CComPtr 提供能夠儲存指標到 COM Automation 元件並藉由使用晚期繫結 (Late Binding) 叫用方法的特製化 IDispatch。 CComDispatchDriver 是 **CComQIPtr<IDispatch, &IIDIDispatch>**的 typedef,它可以隱含地轉換為 CComPtr<IDispatch>。 因此,當這三個任何一方出現在程式碼中,它相當於 CComPtr<IDispatch>。 下列範例顯示如何使用 CComPtr<IDispatch> 取得指標到 Microsoft Word 物件模型。

void COMAutomationSmartPointerDemo()
{

    CComPtr<IDispatch> pWord;
    CComQIPtr<IDispatch, &IID_IDispatch> pqi = pWord;
    CComDispatchDriver pDriver = pqi;

    HRESULT hr;
    _variant_t pOutVal;

    CoInitialize(NULL);
    hr = pWord.CoCreateInstance(L"Word.Application", NULL, CLSCTX_LOCAL_SERVER);    
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Make Word visible.
    hr = pWord.PutPropertyByName(_bstr_t("Visible"),  &_variant_t(1));
    if(FAILED(hr)){ /*... handle hr error*/ }

    // Get the Documents collection and store it in new CComPtr
    hr = pWord.GetPropertyByName(_bstr_t("Documents"), &pOutVal);
    if(FAILED(hr)){ /*... handle hr error*/ }

    CComPtr<IDispatch> pDocuments = pOutVal.pdispVal; 

    // Use Documents to open a document
    hr = pDocuments.Invoke1 (_bstr_t("Open"), &_variant_t("c:\\users\\public\\documents\\sometext.txt"),&pOutVal);
    if(FAILED(hr)){ /*... handle hr error*/ }

    CoUninitialize();
}

請參閱

概念

智慧型指標 (現代 C++)