qobject_cast 是如何工作的?

发布于 2024-10-08 19:16:46 字数 718 浏览 5 评论 0原文

我刚刚在 Qt 中找到了以下代码,我有点困惑这里发生了什么。

特别是 reinterpret_cast(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))));
}

有人愿意解释一下吗?

I just found the following code in Qt and I'm a bit confused what's happening here.

Especially as to what reinterpret_cast<T>(0) does?

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))));
}

Anyone care to explain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

罪#恶を代价 2024-10-15 19:16:46

这有点复杂......

记住 qobject_cast(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; }

因此,如果您有一个 T 类型的对象 x 和一个 y 类型的对象code>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(0) 的用途。我们不需要像 this 这样的实际对象,因为编译器只需要对象类型即可使检查成功。相反,我们在类型 T 的空指针上调用方法。

我认为 C++ 标准不允许这样做,但它可以工作,因为 this 实际上并未在方法内部使用。

This is a little complicated...

Remember that qobject_cast<T>(obj) is a way to dynamically cast a QObject to the target type T which also derives from QObject. Now, for this to work, the macro Q_OBJECT should be included in the definition of class T.

Apparently, the qt_check_for_QOBJECT_macro call is for checking that the class really contains the Q_OBJECT macro. When the macro is expanded, it contains the following definitions:

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; }

So if you have an object x of type T and an object y of type U, the call x->qt_check_for_QOBJECT_macro(y) calls the function qYouForgotTheQ_OBJECT_Macro with parameters of types T* and U*. Because the function is templated with a single type parameter, the types T and U must be the same.

Now, if you call x->qt_check_for_QOBJECT_macro(x) then you should expect the types to be the same and for the compilation to trivially succeed. However, remember that this has the same type as the class the method was defined in. So if x is of a class that was derived from T but doesn't contain its own definition of qt_check_for_QOBJECT_macro, the call will fail.

So we have a way to check if the target type T contains the correct mechanism for the dynamic cast, but we don't have a object of type T to call this method on yet. That's what the reinterpret_cast<T>(0) is for. We don't need an actual object as this, since the compiler only needs the object types for the check to succeed. Instead, we call a method on a null pointer of type T.

I don't think this is allowed by the C++ standard, but it works since this isn't actually used inside the method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文