是否有任何情况应该在 QueryInterface 实现中使用dynamic_cast?

发布于 2024-10-16 02:07:06 字数 628 浏览 1 评论 0原文

实现 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

弃爱 2024-10-23 02:07:06

在那些“支持的接口 id”未知的 QueryInterface 实现中,这是必要的。例如,如果您决定在基类中实现 QueryInterface,而不是为每个派生类重写它。

发生这种情况的情况是有很多相似的类型,其中“相似”意味着“实现许多相同的接口”。即,您有对象类型 Derived1... DerivedN,它们都实现了 Interface1...InterfaceM 的某些子集。

对于游戏引擎来说可能就是这种情况,其中游戏实体都实现了 IMoveableIScriptableIFactoryIShoots 的子集。 code>、IPlayerControlledIStealthyISensor 等。当然,根据 COM 规则,当且仅当工厂也实现 IMovable 时,您必须能够调用 IFactory::QueryInterface 并获取 IMovable* >。

您将如何实现所有这些 QueryInterface 方法?最简单的方法是在 IUnknownIFactory 之间插入 GameObject 基类,并使用 实现 GameObject::QueryInterface >dynamic_cast 检查。这样,您只需要一个实现,而不是具体类型的每个接口一个实现。

It would be necessary in those implementations of QueryInterface where the "supported interface ids" aren't known. E.g. if you decide to implement QueryInterface 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 of Interface1...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 call IFactory::QueryInterface and get an IMovable* if and only if the factory also implements IMovable.

How are you going to implement all those QueryInterface methods? It's easiest to insert an GameObject base class between IUnknown and IFactory, and implement GameObject::QueryInterface using dynamic_cast checks. In this way, you need only one implementation, instead of one per interface of a concrete type.

夏花。依旧 2024-10-23 02:07:06

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文