是否有任何理由反对在QueryInterface()实现中直接调用AddRef()?

时间:2010-05-11 13:38:45

标签: c++ visual-c++ com interop com-interop

在C ++中实现IUnknown::QueryInterface()时,有一些关于指针操作的警告。例如,当类实现多个接口(多重继承)explicit upcasts are necessary

class CMyClass : public IInterface1, public IInterface2 { 
}; 

//inside CMyClass::QueryInterface():
if( iid == __uuidof( IUnknown ) ) { 
     *ppv = static_cast<IInterface1*>( this ); // upcast in order to properly adjust the pointer
     //call Addref(), return S_OK 
} 

在多重继承方案中,upcast的原因非常明显。然而,每次在这里和那里我也看到以下内容:

static_cast<IUnknown*>( *ppv )->AddRef();

而不是简单地从AddRef()实施内部调用QueryInterface()

我是否有理由将先前复制到ppv的值转换为仅调用当前对象上的AddRef()

2 个答案:

答案 0 :(得分:2)

AddRefIUnknown中是纯虚拟的,并且没有其他接口实现它,因此程序中唯一的实现是您在CMyClass中编写的实现。这一方法会覆盖 IInterface1::AddRefIInterface2::AddRefIUnknown没有任何数据成员(例如引用计数),因此菱形问题不会导致您的类容易受到问题的影响,例如对AddRef执行不同数据的不同调用在同一个班级。

this->AddRef()的呼叫将被路由到与static_cast<IUnknown*>(*ppv)->AddRef()相同的位置。我认为没有理由采用更冗长的风格。

答案 1 :(得分:1)

详细语法的原因可能在于ppv中不仅if-else-if可能会返回STDMETHODIMP Car::IternalQueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(&m_innerUnknown); else if (riid == IID_IVehicle) *ppv = static_cast<IVehicle*>(this); else if (riid == IID_ICar) *ppv = static_cast<ICar*>(this); else return (*ppv = 0), E_NOINTERFACE; ((IUnknown*)*ppv)->AddRef(); return S_OK; } ,这在较长的{{1}}中很容易被忽略。 Don Box的Essential COM的一个例子:

{{1}}