qobject_cast如何工作?

ron*_*nag 39 c++ qt casting static-cast reinterpret-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))));
}
Run Code Online (Sandbox Code Playgroud)

有人在乎解释吗?

Amn*_*non 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; }
Run Code Online (Sandbox Code Playgroud)

所以,如果你有一个对象x类型T和对象y类型U,调用x->qt_check_for_QOBJECT_macro(y)调用函数qYouForgotTheQ_OBJECT_Macro与类型的参数T*U*.因为该函数是模板使用单一类型的参数,类型TU必须是相同的.

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

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

我不认为C++标准允许这样做,但它可以工作,因为this实际上并没有在方法中使用.

  • “现在,要使其正常工作,应在类T的定义中包含宏Q_OBJECT。”这可能是错误的。Qt文档[here](http://doc.qt.digia.com/qt/metaobjects.html)说,“虽然可以在没有Q_OBJECT宏和没有元对象代码的情况下将QObject用作基类,但是这两个信号都没有如果不使用Q_OBJECT宏,则插槽和此处描述的其他功能都将不可用。` (2认同)