在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()
?
答案 0 :(得分:2)
AddRef
在IUnknown
中是纯虚拟的,并且没有其他接口实现它,因此程序中唯一的实现是您在CMyClass
中编写的实现。这一方法会覆盖 IInterface1::AddRef
和IInterface2::AddRef
。 IUnknown
没有任何数据成员(例如引用计数),因此菱形问题不会导致您的类容易受到问题的影响,例如对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}}