【问题标题】:Is there any case when dynamic_cast should be used in the QueryInterface implementation?在 QueryInterface 实现中是否应该使用 dynamic_cast ?
【发布时间】:2011-06-20 13:00:02
【问题描述】:

实现IUnknown::QueryInterface() 的典型方式如下:为每个支持的接口ID 使用if-else-if 链并执行以下操作:

if( iid == __uuidof( IInterfaceN ) ) {
   *ppv = static_cast<IInterfaceN>( this );
   //call Addref(), return S_OK
} 

现在static_castis necessary在这里进行多继承场景中的正确指针调整。

偶尔我会看到使用dynamic_cast 的实现。 IMO 那是在浪费时间 - 结果是一样的,只是需要更长的时间,并且会使实施过度设计。

在将this指针复制到IUnknown::QueryInterface()实现的void**参数之前,确实需要使用dynamic_cast来转换它吗?

【问题讨论】:

    标签: c++ com casting multiple-inheritance


    【解决方案1】:

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

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

    这可能是游戏引擎的情况,其中游戏实体都实现了IMoveableIScriptableIFactoryIShootsIPlayerControlledIStealthyISensor 等的子集。当然,根据 COM 规则,当且仅当工厂也实现 IMovable 时,您必须能够调用 IFactory::QueryInterface 并获得 IMovable*

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

    【讨论】:

    • Emm...您能否提供一些此类层次结构的最简单示例?
    • 假设一个Base 和一组Derived1...DerivedN 类,其中Derived 类每个实现Interface1...InterfaceM 的随机子集。在Base::QueryInterface 中,您将检查this 是否可以成为所需接口的dynamic_cast
    • 好的,我明白了,这是一个有效的例子,虽然有点过度设计。您能否将其包含在答案中?
    【解决方案2】:

    QueryInterface() 实际上是“动态转换”运算符的实现。将实现建立在另一个需要相同元数据(继承树)的另一个变体的实现之上是没有实际意义的。

    一个好的编译器应该能够将其重新映射为static_cast

    【讨论】:

    • 你能举个具体的例子吗?
    猜你喜欢
    • 2010-11-28
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多