是否有任何情况应该在 QueryInterface 实现中使用dynamic_cast?
实现 IUnknown::QueryInterface()
的典型方法如下:对每个受支持的接口 id 使用一系列 if-else-if
并执行以下操作:
if( iid == __uuidof( IInterfaceN ) ) {
*ppv = static_cast<IInterfaceN>( this );
//call Addref(), return S_OK
}
现在 < code>static_cast 对于多重继承场景中正确的指针调整是必要的。
有时我会看到使用 dynamic_cast
的实现。在我看来,这是浪费时间——结果是一样的,只是需要更长的时间,并使实现过度设计。
在将 this
指针复制到 IUnknown:: 的
实现?void**
参数之前,是否确实需要使用 dynamic_cast
来转换 this
指针? QueryInterface()
The typical way of implementing IUnknown::QueryInterface()
is the following: use a chain of if-else-if
for each supported interface id and do the following:
if( iid == __uuidof( IInterfaceN ) ) {
*ppv = static_cast<IInterfaceN>( this );
//call Addref(), return S_OK
}
Now static_cast
is necessary here for proper pointer adjustment in multiple inheritance scenario.
Once in a while I see implementations that instead use dynamic_cast
. IMO that's a waste of time - result will be the same, it'll just take longer and make the implementation overengineered.
Is there any case when using dynamic_cast
is indeed necessary for casting this
pointer before copying it into void**
parameter of IUnknown::QueryInterface()
implementation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在那些“支持的接口 id”未知的 QueryInterface 实现中,这是必要的。例如,如果您决定在基类中实现 QueryInterface,而不是为每个派生类重写它。
发生这种情况的情况是有很多相似的类型,其中“相似”意味着“实现许多相同的接口”。即,您有对象类型
Derived1
...DerivedN
,它们都实现了Interface1
...InterfaceM
的某些子集。对于游戏引擎来说可能就是这种情况,其中游戏实体都实现了
IMoveable
、IScriptable
、IFactory
、IShoots
的子集。 code>、IPlayerControlled
、IStealthy
、ISensor
等。当然,根据 COM 规则,当且仅当工厂也实现IMovable
时,您必须能够调用IFactory::QueryInterface
并获取IMovable*
>。您将如何实现所有这些 QueryInterface 方法?最简单的方法是在
IUnknown
和IFactory
之间插入GameObject
基类,并使用实现
检查。这样,您只需要一个实现,而不是具体类型的每个接口一个实现。GameObject::QueryInterface
>dynamic_castIt would be necessary in those implementations of
QueryInterface
where the "supported interface ids" aren't known. E.g. if you decide to implementQueryInterface
in a base class, and not override it for every derived class.A case where this would happen is the situation where you have a lot of similar types, where "similar" means "implementing many of the same interfaces". I.e. you have object types
Derived1
...DerivedN
which all implement some subset ofInterface1
...InterfaceM
.This could be the case for a game engine where game entities all implement a subset of
IMoveable
,IScriptable
,IFactory
,IShoots
,IPlayerControlled
,IStealthy
,ISensor
, etcetera. Of course, by COM rules you must be able to callIFactory::QueryInterface
and get anIMovable*
if and only if the factory also implementsIMovable
.How are you going to implement all those
QueryInterface
methods? It's easiest to insert anGameObject
base class betweenIUnknown
andIFactory
, and implementGameObject::QueryInterface
usingdynamic_cast
checks. In this way, you need only one implementation, instead of one per interface of a concrete type.QueryInterface()
实际上是“动态转换”运算符的实现。将实现建立在需要相同元数据(继承树)的另一个变体的另一个实现之上是没有任何意义的。一个好的编译器应该能够将其重新映射到
static_cast
中。QueryInterface()
is in fact an implementation of a "dynamic cast" operator. Basing the implementation on top of another implementation that requires another variant of the same metadata (inheritance tree) makes no real sense.A good compiler should be able to remap this into a
static_cast
.