40

我刚刚在 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))));
}

有人愿意解释吗?

4

1 回答 1

38

这有点复杂……

请记住,这qobject_cast<T>(obj)是一种将 a 动态QObject转换为T也派生自QObject. 现在,为了让它工作,宏Q_OBJECT应该包含在 class 的定义中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的对象和一个类型的对象yU调用将调用带有类型和参数x->qt_check_for_QOBJECT_macro(y)的函数。因为该函数是使用单个类型参数模板化的,所以类型和必​​须相同。qYouForgotTheQ_OBJECT_MacroT*U*TU

现在,如果您调用,x->qt_check_for_QOBJECT_macro(x)那么您应该期望类型相同并且编译会轻松成功。但是,请记住,this它与定义该方法的类具有相同的类型。因此,如果x是从 T 派生但不包含其自己的定义的类qt_check_for_QOBJECT_macro,则调用将失败。

所以我们有办法检查目标类型 T 是否包含正确的动态转换机制,但是我们还没有 T 类型的对象来调用这个方法。这就是它的reinterpret_cast<T>(0)用途。我们不需要实际的对象 as this,因为编译器只需要对象类型就可以成功检查。相反,我们在 T 类型的空指针上调用方法。

我认为 C++ 标准不允许这样做,但它确实有效,因为this它实际上并没有在方法中使用。

于 2010-12-23T11:32:23.210 回答