qobject_cast如何工作?

时间:2010-12-23 11:02:39

标签: c++ qt casting reinterpret-cast static-cast

我刚刚在Qt中找到了以下代码,我对这里发生的事情感到有些困惑。

特别是关于reinterpret_cast<T>(0)做什么?

template <class T>
inline T qobject_cast(const QObject *object)
{
    // this will cause a compilation error if T is not const
    register T ptr = static_cast<T>(object);
    Q_UNUSED(ptr);

#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
    reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
#endif
    return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));
}

有人在乎解释吗?

1 个答案:

答案 0 :(得分:38)

这有点复杂......

请注意,qobject_cast<T>(obj)是一种动态投放QObject到目标类型T的方法,该目标类型也来自QObject。现在,为了实现这一点,宏Q_OBJECT应该包含在类T的定义中。

显然,qt_check_for_QOBJECT_macro调用用于检查该类是否确实包含Q_OBJECT宏。扩展宏时,它包含以下定义:

template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const 
   { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }

template <typename T1, typename T2>
inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }

因此,如果您有类型为x的对象T和类型为y的对象U,则调用x->qt_check_for_QOBJECT_macro(y)会调用函数{{1参数类型为qYouForgotTheQ_OBJECT_MacroT*的参数。由于该函数使用单个类型参数进行模板化,因此U*T类型必须相同。

现在,如果你调用U,那么你应该期望这些类型是相同的,并且编译很容易成功。但是,请记住x->qt_check_for_QOBJECT_macro(x)与定义方法的类具有相同的类型。因此,如果this是从T派生但不包含其自己的{{1}定义的类调用将失败。

因此我们有办法检查目标类型T是否包含动态强制转换的正确机制,但我们还没有类型为T的对象来调用此方法。这就是x的用途。我们不需要实际对象qt_check_for_QOBJECT_macro,因为编译器只需要检查的对象类型成功。相反,我们在类型为T的空指针上调用一个方法。

我不认为C ++标准允许这样做,但是它起作用,因为reinterpret_cast<T>(0)实际上并没有在方法中使用。