2011-11-10 36 views
1

我對通過IDispatch/IUnknown指針看到的__vfptr感到困惑。 我正在創建自由線程的COM obj(IMyContainer)。在這個對象的內部,我需要保留指向2個實現相同IMyInterface的com對象的不同實例。所以我調用CreateAndSaveDispToMap()兩次。爲什麼我爲兩個不同的實例獲得相同的__vfptr?

我的想法是保持他們的IDispatch指針在一些std :: map。在這一刻,我懷疑每個實例的refCount都是1.它就是這樣。但令人驚訝的是,我看到我得到了相同的__vftbl通過pUnk 2個不同的調度指針。

爲什麼? AddRef()和Release()可能工作正常嗎?

HRESULT CMyContainer::CreateAndSaveDispToMap(...) 
{ 
... 
IMyInterface* pMyInterface = NULL; 
hr = ::CoCreateInstance(CLSID_MyInterface, NULL, CLSCTX_INPROC_SERVER, IID_IMyInterface, (void**)&pMyInterface); 
pMyInterface->QueryInterface(IID_IDispatch, (void**)&pDisp); 
pMyInterface->Release(); // Call Release since QI already called AddRef() 
... 

IUnknown* pUnk = NULL; 
pDisp->QueryInterface(IID_IUnknown, (void**)&pUnk); 
int refCount = pUnk->Release(); 
... 
AddToMap(pDisp); 
} 
+0

v-表只是一個地址表。所有對象實例都有* one * v-table,它不存儲任何對象狀態。 –

回答

0

每個多態對象都有一個__vfptr,它是一個指向對象實際類的vtable的指針。每個不同的類都生成一個vtable。這就是爲什麼同一班級的任何兩個物體的__vfptr將具有相同的值。

區分不同的COM對象檢索並比較它們的接口指針。這就是object identity

0

謝謝,我發現函數在IUnknown上的地址是一樣的,必須是這樣的。

但是還是不要低估AddRef/Release的行爲。當我在ExposePointer()中進入調試模式時,我發現第二個連續調用不會將refCount帶到3.它會將它返回到2.

但是,如果我調用兩次ForgetExposePointer(),它會將它帶到3.

爲什麼通過Variant * Result返回調度指針或忘記返回這樣的值給我不同的結果?我認爲在呼叫1和呼叫2之間發生一些對Release()發生的隱藏呼叫...

STDMETHODIMP CMyContainer::ExposePointer([in]int index, [out, retval] VARIANT* Result) 
{ 
VariantInit(Result); 
IDispatch* pDisp = m_map[index].second; 
V_VT(Result) = VT_DISPATCH; 
V_DISPATCH(Result) = pDisp; 
refCount_x = pDisp->AddRef(); // Increment, because we expose 
} 

STDMETHODIMP CMyContainer::ForgetExposePointer([in]int index, [out, retval] VARIANT* Result) 
{ 
VariantInit(Result); 
IDispatch* pDisp = m_map[index].second; 
refCount_y = pDisp->AddRef(); 
} 


MyApp::Function1(...) 
{ 
CreateAndSaveDispToMap(...); // refCount is 1 now 
VARIANT var1; 
VARIANT var2; 
pMyContainer->ExposePointer(index, &var1); // Call 1 
pMyContainer->ExposePointer(index, &var2); // Call 2 
} 
MyApp::Function2(...) 
{ 
CreateAndSaveDispToMap(...); // refCount is 1 now 
VARIANT var1; 
VARIANT var2; 
pMyContainer->ForgetExposePointer(index, &var1); 
pMyContainer->ForgetExposePointer(index, &var2); 
} 
相關問題