2016-02-22 25 views
2

我有興趣比較兩個IDirect3DDevice9 COM指針,它們繼承IUnknown以實現相等性。基於一個similar topic,我明白你可以爲QIIUnknown兩個指針,並比較結果的平等。然而,我很好奇,如果我們可以通過一個IsEqual方法完成同樣的事情,直接使用兩個IUnknown指針,讓繼承確定相關的指針IUnknown,並將其用於相等性檢查。根據我的實驗,這似乎工作,並不需要QIrelease操作(或者可能隱式完成)。如果有任何警告,保證此建議無效,請讓我知道。通過QI或繼承的IUnknown相等之間的區別

BOOL IsEqual(IUnknown *pA, IUnknown *pB) 
{ 
    return (pA == pB); 
} 

BOOL IsEqual (IDirect3DDevice9 *pDevice1, IDirect3DDevice9 *pDevice2) 
{ 
    IUnknown *u1, *u2; 

    pDevice1->QueryInterface(IID_IUnknown, &u1); 
    pDevice2->QueryInterface(IID_IUnknown, &u2); 

    BOOL areSame = u1 == u2; 
    u1->Release(); 
    u2->Release(); 

    return areSame; 
} 
+0

實際上,我認爲這些情況更多,我認爲第一次IsEqual檢查並不能保證按預期工作,因爲傳入方法的IUnknown指針僅代表相同的IDirect3DDevice9指針。因此,如果兩個指針的開頭不同,那麼相等性檢查就會失敗。 – lancery

+1

不,您的編譯器不知道如何調用QueryInterface()。它會假定指針已經兼容,因爲IUnknown是基本接口,並且不會嘗試轉換它。哪個產生錯誤的結果,需要QI。您可以使用C++中的CComQIPtr類來處理QI調用和Release()調用。 –

+0

如果所有COM組件都作爲C++類實現並且不存在多重繼承和聚合,那麼* *可能會工作,但事實並非如此。實際上,* COM Tutorial Samples *推薦在嵌套類中實現接口,這使得聚合支持更容易。這使得查詢IUnknown是強制性的。 – Medinoc

回答

2

下面是一些具有多重繼承的示例代碼。這裏IUnknown在層次結構中發生兩次,但其他接口也可能發生兩次。

我使用的功能並非特定於Visual C++,因此此代碼更容易嘗試聯機編譯器服務。

#include <stdio.h> 

class IUnknown {}; 

class IInterface1 : public IUnknown {}; 

class IInterface2 : public IUnknown {}; 

class Class : public IInterface1, public IInterface2 {}; 

int main() { 
    Class object; 

    // Please note that only implicit conversions are used - 
    // exactly as if you were passing Derived* pointers into 
    // a function that accepts Base* pointers  
    IInterface1* interface1 = &object; 
    IUnknown* unknown1 = interface1; 
    IInterface2* interface2 = &object; 
    IUnknown* unknown2 = interface2; 

    printf("%p %p %s", unknown1, unknown2, 
     (unknown1 == unknown2) ? "true" : "false"); 
} 

這段代碼的輸出是:

0xbfc8e9de 0xbfc8e9df假

所以,不,你不能依靠upcasts檢查的indentity - 你開始你可以得到不同的走隨目標爲同一個對象。這正是爲什麼此代碼無法編譯的原因:

IUnknown* unknown = &object;//WON'T COMPILE 

因爲轉換不明確。只有當你告訴使用哪個繼承路徑才能編譯代碼。一旦你選擇了路徑,你可能會得到相同基類的不同子對象,當然這些子對象將位於不同的地址。

相關問題