【问题标题】:Downcast using C-style cast when knowing the concrete sub class type在知道具体的子类类型时使用 C 风格的强制转换
【发布时间】:2012-09-25 23:42:24
【问题描述】:

在我的项目中,我有一棵不同类型的 QObjects 树。让我给你一个简单的例子,它应该让你明白我在说什么。这可能是一个示例 QObject 树(不是继承图,但有点类似于类图),我们从顶部的根对象开始,并在下面列出其子对象:

                                   City
                                     |
                                  Street
                                 /      \
                            House       ...
                           /     \
                       Floor     ...
                       /   \
                   Room    ...

虽然 QObject 树不一定遵循此规则,但在我的例子中,树中的每个类都有一个 特定 类型的父级。因此,以一个关系为例,一个房子可以有一些楼层和其他类型的孩子,但一个楼层是房子的孩子,只是一个房子

现在,如果我将它们建模为 QObject 派生类,class Floor 的接口应该通过内部查看 QObject::parent() 是什么来给我它的 House *house()。我真的知道这个父级将是House* 类型,因为我将它设计成这样,并且程序员坚持这种设计。

如果我将QObject *parent() 转换为House* 以实现House *house() const,可以吗?

Qt 建议使用qobject_cast<House*>(parent()),如果QObject* parent() 不继承自House,则返回0,从而使转换类型安全。但在发布模式下,我想避免这种缓慢的演员阵容。我分析了一种特定的算法,它在执行 C 样式转换而不是 qobject_casts 时执行速度快三倍。这是因为 qobject_cast 在运行时向元对象询问类型信息,当经常调用 非常 时会导致相当大的速度下降。

所以我最终得到的是:

House *Floor::house() const {
    Q_ASSERT(qobject_cast<House*>(parent()));
    return (House*)parent();
}

这将在调试模式下断言父级确实是 House,而在发布模式下仅有效地进行 C 样式转换。

言归正传:我知道当 C++ 程序员进行 C 风格转换时人们会大喊大叫,但在这种情况下可以吗?

另一种解决方案是将特定类型的父指针另外存储为成员变量,但我认为这是多余的,我也喜欢树反映在返回树父的那些方法中。

【问题讨论】:

    标签: c++ qt casting downcast


    【解决方案1】:

    如果您确定所有权图不会更改,即使在维护期间也是如此,那么未经类型检查的强制转换是安全的。您可以使用速度很快的static_cast&lt;House*&gt;(parent()),或者,如果您真的想要,可以使用 C 风格的演员表。但是 C 风格的转换并不比 C++ static_cast 快。

    【讨论】:

    • 我认为你误解了我的图表。它不是继承图,而是 QObject 关系图(QObject 树)。我会在我的问题中澄清这一点,很抱歉在这一点上有点不准确。
    • @leemes - 是的,我在发帖后就意识到了这一点。在一两分钟内查看我的编辑。不过,本质上是相同的逻辑。
    • 谢谢。我从不理解 C 风格转换和 static_cast 之间的区别...现在类型将匹配。
    • @leemes - C 风格的演员是一把大锤。 C++ 强制转换更有技巧。如果您将static_cast 视为撤消隐式转换,那么您将不会大错特错。在这种情况下,House 派生自QObject,因此House* 在内部转换为QObject*static_cast 正好相反。
    猜你喜欢
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 2010-09-27
    相关资源
    最近更新 更多