假设我的COM对象实现了两个或多个COM接口:
class CMyClass : public IPersistFile, public IPersistStream { };
当实现QueryInterface()我需要能够返回一个IUnknown *指针。 由于两个基本接口都是从IUnknown派生的,所以我不能隐式地上传 – 这样的上传会是不明确的。 为了明确地上传,我需要使用以下两种方法之一:
if( iid == __uuidof( IUnknown ) ) { *ppv = static_cast<IPersistFile*>( this ); static_cast<IPersistFile*>( this )->AddRef(); return S_OK; }
要么
if( iid == __uuidof( IUnknown ) ) { *ppv = static_cast<IPersistStream*>( this ); static_cast<IPersistStream*>( this )->AddRef(); return S_OK; }
看起来唯一的要求是,每当在一个对象上调用QI()时,每次都返回相同的指针,如果我select了任何一个强制转换,并且坚持它,我就满足了这个要求。
我应该select哪个upcast?为什么?
Mark Ransom已经给出了正确的答案 – 只要一致,任何事情都可以做 – 但挑选第一个有一个小小的优势。 由于布局规则,第一个接口的IUnknown*
将指向对象的开始。 任何其他IUnknown*
将指向对象中其他位置的后续vtable指针。 出于调试目的,了解ano对象在内存中的起始位置非常有用。
无论你使用哪个upcast,只要你总是使用同一个。 我只是选择一个约定,比如总是返回继承列表中声明的第一个约定。
IU已知未实现。 你需要提供IUnknown的所有实现。 因此,对于我所知道的,你返回这个指针。
AddRef,Release和QI都是由你实现的,而不是在父接口上实现的,所以你只要调用addref就没有问题,不需要强制转换。
通常情况下,如果你想向IUnknown投射一个具有来自IUnknown的多重继承的对象,你将它转换到其接口之一,然后转换为IUnknown …