qobject_cast 是如何工作的?
我刚刚在 Qt 中找到了以下代码,我有点困惑这里发生了什么。
特别是 reinterpret_cast
的作用是什么?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这有点复杂......
记住
qobject_cast(obj )
是一种将QObject
动态转换为目标类型T
的方法,该目标类型也派生自QObject
。现在,要使其正常工作,宏Q_OBJECT
应该包含在类T
的定义中。显然,
qt_check_for_QOBJECT_macro
调用是为了检查该类是否确实包含 Q_OBJECT 宏。当宏展开时,它包含以下定义:因此,如果您有一个
T
类型的对象x
和一个y
类型的对象code>U,调用x->qt_check_for_QOBJECT_macro(y)
调用函数qYouForgotTheQ_OBJECT_Macro
,参数类型为T*
和U*
。由于该函数是使用单个类型参数进行模板化的,因此类型T
和U
必须相同。现在,如果您调用 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 aQObject
to the target typeT
which also derives fromQObject
. Now, for this to work, the macroQ_OBJECT
should be included in the definition of classT
.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:So if you have an object
x
of typeT
and an objecty
of typeU
, the callx->qt_check_for_QOBJECT_macro(y)
calls the functionqYouForgotTheQ_OBJECT_Macro
with parameters of typesT*
andU*
. Because the function is templated with a single type parameter, the typesT
andU
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 thatthis
has the same type as the class the method was defined in. So ifx
is of a class that was derived from T but doesn't contain its own definition ofqt_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 asthis
, 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.