共用方式為


向物件請求介面

我們稍早看到物件可以實作多個介面。 Common Item Dialog 物件是現實世界的一個例子。 為了支援最典型的用法,物件會實作 IFileOpenDialog 介面。 這個介面會定義顯示對話框和取得所選檔案相關信息的基本方法。 不過,為了更進階的使用,物件也會實作名為 IFileDialogCustomize的介面。 程式可以使用這個介面來透過新增使用者介面控制項,定制對話框的外觀和行為。

回想一下,每個 COM 介面都必須直接或間接繼承自 IUnknown介面。 下圖顯示 Common Item Dialog 對象的繼承。

顯示通用項目對話框物件所公開介面的圖表

如圖表所示,IFileOpenDialog 的直接上階是 IFileDialog 介面,接著會繼承 IModalWindow。 當您從 IFileOpenDialog 上移至 IModalWindow 繼承鏈結時,介面會定義越來越一般化的視窗功能。 最後,IModalWindow 介面繼承 IUnknown。 Common Item Dialog 物件也會實作 IFileDialogCustomize,其存在於個別的繼承鏈結中。

現在假設您有一個指向 IFileOpenDialog介面的指標。 如何取得 IFileDialogCustomize 介面的指標?

圖表,顯示相同物件上介面的兩個介面指標

IFileOpenDialog 指標直接轉換成 IFileDialogCustomize 指標是行不通的。 在沒有某種形式的運行時期型別資訊(RTTI)的情況下,沒有可靠的方法可以在繼承層次結構中進行「交叉轉型」,而RTTI是一個取決於程式語言的功能。

COM 方法是 要求 物件提供 IFileDialogCustomize 指標,並使用第一個介面做為對象的連線。 這是藉由從第一個介面指標呼叫 IUnknown::QueryInterface 方法來完成。 您可以將 QueryInterface 視為 C++ 中與語言無關的 dynamic_cast 關鍵詞版本。

QueryInterface 方法具有下列簽章:

HRESULT QueryInterface(REFIID riid, void **ppvObject);

根據您已經知道的 CoCreateInstance,您可以猜測 QueryInterface 如何運作。

  • riid 參數是識別您要求之介面的 GUID。 reFIID 數據類型是 const GUID&typedef。 請注意,不需要類別標識碼 (CLSID),因為對象已經建立。 只需要介面識別碼。
  • ppvObject 參數會接收介面的指標。 此參數的數據類型 void**,因為 CoCreateInstance 使用此數據類型的原因相同:QueryInterface 可用來查詢任何 COM 介面,因此參數無法強型別。

以下說明如何呼叫 QueryInterface,以取得 IFileDialogCustomize 指標:

hr = pFileOpen->QueryInterface(IID_IFileDialogCustomize, 
    reinterpret_cast<void**>(&pCustom));
if (SUCCEEDED(hr))
{
    // Use the interface. (Not shown.)
    // ...

    pCustom->Release();
}
else
{
    // Handle the error.
}

一如往常,檢查 HRESULT 傳回值,以防方法失敗。 如果方法成功,您必須在完成使用指標後呼叫 Release,如 管理物件存留期中所述。

下一步

COM 中的 記憶體配置