COM學習筆記3_IUnknown的三個接口函數

對於COM組件,正確處理IUnknown的三個接口函數非常重要。

對於QueryInterface,一個參考處理如下:

 

這裏要注意的一點就是當iid == IID_IUnknown時,返回的並不是
static_cast<IUnknown*>(this) ;
而是
static_cast<IX*>(this) ;
這是因爲把this轉爲IUnknown*是不明確的(IX和IY都從IUnknown派生)。
另外IX和IY並不按虛擬方式從IUnknown派生,是因爲虛擬派生可能產生與COM不兼容的vtbl。

QueryInterface可以有不同的實現,只需要遵循一定的規則。這些規則可見《COM技術內幕》3.2節。

AddRef和Release的一個簡單實現如下:

 

組件的實現很簡單,但客戶端使用起來可就不那麼容易,客戶必須記得用完每一個接口指針後調用Release。
這可不是一個簡單的工作!

上面那個實現是爲整個組件維護引用計數。也可以爲每一個接口維護引用計數,
這樣可以方便調試程序,也能支持資源的按需獲取。
所以,客戶必須在使用完某接口後,對該接口調用Release,而不是該組件的其它接口(這應該作爲一個規則強制執行!)

無論如何,用戶手動調用AddRef,Release都是一件非常麻煩的事情,另外QueryInterface中的void**參數也不是類型安全的。
所以可以使用智能接口指針簡化編程(相當於添加中間層)。
在ATL中提供了兩個COM接口指針類:CComPtr和CComQIPtr。

注:若需要手動釋放智能接口指針所指向的接口,不能通過簡單通過->轉發Release操作。
例如:

 

爲了避免用戶像這樣spIX->Release ()調用Release,CComPtr在重載->操作符時,不是簡單把內部接口指針返回,而是定義了一個類:

 

_NoAddRefReleaseOnCComPtr禁用了可能的AddRef,Release操作,
然後再這樣實現->操作符重載

 

這樣如果用戶像這樣操作spIX->Release ()會遭遇一個編譯錯誤。

 

發佈了59 篇原創文章 · 獲贊 9 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章