我有一个 COM 接口,其中有一个返回对象的方法:
interface ICreatorInterface {
HRESULT CreateObject( IObjectToCreate** );
};
关键是调用ICreatorInterface::CreateObject()
是检索对象实现的唯一方法IObjectToCreate
界面。
在 C++ 中我可以这样做:
HRESULT CCreatorInterfaceImpl::CreateObject( IObjectToCreate** result )
{
//CObjectToCreateImpl constructor sets reference count to 0
CObjectToCreateImpl* newObject = new CObjectToCreateImpl();
HRESULT hr = newObject->QueryInterface( __uuidof(IObjectToCreate), (void**)result );
if( FAILED(hr) ) {
delete newObject;
}
return hr;
}
或者这样
HRESULT CCreatorInterfaceImpl::CreateObject( IObjectToCreate** result )
{
//CObjectToCreateImpl constructor sets reference count to 1
CObjectToCreateImpl* newObject = new CObjectToCreateImpl();
HRESULT hr = newObject->QueryInterface( __uuidof(IObjectToCreate), (void**)result );
// if QI() failed reference count is still 1 so this will delete the object
newObject->Release();
return hr;
}
不同之处在于引用计数器的初始化方式以及万一情况下对象删除的实现方式QueryInterface()
失败。因为我完全控制两者CCreatorInterfaceImpl
and CObjectToCreateImpl
我可以选择任何一种方式。
IMO 第一个变体更清晰 - 所有引用计数的东西都在一段代码中。我有监督什么吗?为什么第二种方法会更好?以上哪一个更好,为什么?
这两种变体都违反了 COM 的一个非常基本的原则
- 切勿对引用计数为零的 COM 对象调用除 AddRef 之外的任何方法。
否则会导致各种错误。简单地说,因为它阻止人们对对象进行完全合法的操作。就像把它们放入智能指针一样。智能指针将调用 AddRef,将计数设置为 1,然后 Release 将计数设置为 0 并导致对象自毁。
是的,我意识到 90% 的 QueryInterface 实现都没有这样做。但我也向你保证,有一些可以做到:)
我认为最简单的方法是在创建对象后立即调用 AddRef。这允许对象尽早表现得像普通 COM 对象一样。
我过去遇到过这个问题,并且编写了一个很好的小帮助器方法(假设该对象是在 ATL 中实现的)。
template <class T>
static
HRESULT CreateWithRef(T** ppObject)
{
CComObject<T> *pObject;
HRESULT hr = CComObject<T>::CreateInstance(&pObject);
if ( SUCCEEDED(hr) )
{
pObject->AddRef();
*ppObject = pObject;
}
return hr;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)