【问题标题】:C++: Cast to an interface that is not part of the base classC++:转换为不属于基类的接口
【发布时间】:2010-07-13 16:56:37
【问题描述】:

我有一系列代表“智能”地图元素的类:MapTextElementMapIconElement 等。这些类扩展了各种 Qt 图形项类,但也提供了通用功能,例如返回的抽象工厂方法专门针对每个类的属性面板。我已经在一个纯虚类MapElementInterface 中声明了这些常用方法。然后我的类乘以继承适当的 Qt 基类以及接口:

class MapTextElement : public QGraphicsTextItem, public MapElementInterface
class MapIconElement : public QGraphicsItem, public MapElementInterface

所以我的类层次结构看起来有点像:

         +-------------+    +-------------------+
         |QGraphicsItem|    |MapElementInterface|
         +-------------+    +-------------------+
                ^                   ^   ^
                |                   |   |
         +------+------+            |   |    
         |             |            |   |
+-----------------+   +--------------+  |
|QGraphicsTextItem|   |MapIconElement|  |
+-----------------+   +--------------+  |
     ^                                  |
     |                                  |
     +-------------------+        +-----+
                         |        |
                      +--------------+
                      |MapTextElement|
                      +--------------+

我从 Qt 提供的方法接收到一个指向 QGraphicsItem 的指针。在这种情况下,我知道指针不仅是QGraphicsItem,还有MapElementInterface。我想将指针视为MapElementInterface

QList<QGraphicsItem*> selected = scene_->selectedItems();
if (selected.count() == 1) {
  // We know that the selected item implements MapEditorInterface
  MapElementInterface *element = SOME_CAST_HERE<MapElementInterface*>(selected[0]);
  QWidget *panel = element->GeneratePropertyPanel(property_dock_);
}

正确的演员阵容是什么?还是我完全走错了路?

【问题讨论】:

  • 不能在类层次结构中水平投射,因为 QGraphicsItem 和 MapElementInterface 不相关。您必须向上转换为派生类型,然后再向下转换(使用 dynamic_cast)
  • @Martin:它确实似乎使用直接dynamic_cast工作。您能否向我指出一篇在线文章,该文章更详细地解释了您预期的问题或“陷阱”?谢谢!
  • 当我尝试在两种不相关的“QGraphicsItem 和 MapElementInterface”类型之间进行动态转换时,它返回一个 NULL 指针。因此,您必须在做其他事情,否则两者之间存在某种关系。您只能通过将 (dynamic_cast) 向上转换然后向下转换来从一个转换到另一个。如果您使用的是另一个演员表 (rinterpret_cast),那么您处于未定义的领域。
  • @Martin:您能告诉我您使用的是什么编译器/运行时吗?也许我们看到的行为会因环境而异。很高兴知道。此外,您正在尝试从 pointermultiply-inherited 对象的 dynamic_cast,就像我的示例一样,对吧?
  • gcc(3.? 和 4.2)和开发工作室 10。但这就是 dynamic_cast 应该做的。如果类型之间没有关系(如上所述),则它必须返回 NULL。因此,您要么使用不同的演员表(这是错误的),要么您未提及的类型之间存在另一种关系,或者您正在上下树进行多次演员表。

标签: c++ casting multiple-inheritance


【解决方案1】:

对于多重继承,dynamic_cast 是唯一的方法,并检查返回值是否为 NULL。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      这里你必须小心,因为给定图表,你的指针可能指向 MapTextElement 或 MapIconElement。对您来说,唯一安全的选择是使用动态投射。或者为自己提供另一种方式来确定对象的类型。

      【讨论】:

        【解决方案4】:

        您可以先转换为 MapIconElement,然后再转换为 MapElementInterface,也可以转换为 MapTextElement,然后再转换为 MapElementInterface。您必须选择一条路径(或动态向下转换以检查您选择的路径)。

        【讨论】:

        • 你能澄清一下吗?您是说没有办法直接转换为 MapElementInterface 吗?如果是这样的话,那么每次我添加一个新的 MapElementInterface 的具体类时,我都必须在我的代码中添加另一个 if 路径。这闻起来很臭,并且在很大程度上违背了界面的目的。
        • 没错。恐怕你必须向下动态转换(确实不酷),或者将MapElementInterface变成QGraphicsItem的派生类。或者也许将 MapElementInterface 继承转换为 ...Element 的某个成员。
        • dynamic_cast 似乎对我有用,所以我一定不会遇到您描述的问题。无论如何感谢您的帮助!
        猜你喜欢
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        相关资源
        最近更新 更多