实现IUnknown::QueryInterface()
的典型方法如下:对每个支持的接口ID使用if-else-if
链并执行以下操作:
if( iid == __uuidof( IInterfaceN ) ) {
*ppv = static_cast<IInterfaceN>( this );
//call Addref(), return S_OK
}
现在static_cast
is necessary在多继承方案中进行适当的指针调整。
我偶尔会看到使用dynamic_cast
的实现。国际海事组织浪费时间 - 结果将是相同的,它只需要更长的时间,并使实施过度工程。
在将dynamic_cast
指针复制到this
void**
实现的IUnknown::QueryInterface()
参数之前,是否确实需要使用{{1}}指针?
答案 0 :(得分:1)
在QueryInterface
的那些实现中,有必要使用“支持的接口ID”。例如。如果您决定在基类中实现QueryInterface
,而不是为每个派生类重写它。
出现这种情况的情况是你有很多类似的类型,其中“类似”意味着“实现许多相同的接口”。即您有对象类型Derived1
... DerivedN
,它们都实现了Interface1
... InterfaceM
的某些子集。
这可能是游戏引擎的情况,其中游戏实体都实现了IMoveable
,IScriptable
,IFactory
,IShoots
,IPlayerControlled
的子集, IStealthy
,ISensor
,等等。当然,通过COM规则,当且仅当工厂还实现IFactory::QueryInterface
时,您必须能够调用IMovable*
并获得IMovable
。
您打算如何实施所有这些QueryInterface
方法?最简单的方法是在GameObject
和IUnknown
之间插入IFactory
基类,并使用GameObject::QueryInterface
检查实现dynamic_cast
。通过这种方式,您只需要一个实现,而不是每个具体类型的接口。
答案 1 :(得分:1)
QueryInterface()
实际上是“动态强制转换”运算符的实现。将实现基于另一个需要另一个相同元数据变体(继承树)的实现,这没有任何意义。
一个好的编译器应该能够将其重新映射为static_cast
。