C++ qobject_cast 如何工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4518163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does qobject_cast work?
提问by ronag
I just found the following code in Qt and I'm a bit confused what's happening here.
我刚刚在 Qt 中找到了以下代码,我对这里发生的事情感到有些困惑。
Especially as to what reinterpret_cast<T>(0)
does?
特别是关于什么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))));
}
Anyone care to explain?
有人愿意解释吗?
采纳答案by Amnon
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
.
请记住,这qobject_cast<T>(obj)
是一种将 a 动态QObject
转换为T
也源自QObject
. 现在,为了使其工作,宏Q_OBJECT
应该包含在 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:
显然,该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; }
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.
所以,如果你有一个对象x
类型T
和对象y
类型U
,调用x->qt_check_for_QOBJECT_macro(y)
调用函数qYouForgotTheQ_OBJECT_Macro
与类型的参数T*
和U*
。因为函数是用单个类型参数模板化的,所以类型T
和U
必须相同。
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.
现在,如果您调用,x->qt_check_for_QOBJECT_macro(x)
那么您应该期望类型相同并且编译成功。但是,请记住,this
它与定义方法的类具有相同的类型。因此,如果x
是从 T 派生的类,但不包含其自己的 定义qt_check_for_QOBJECT_macro
,则调用将失败。
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.
所以我们有一种方法可以检查目标类型 T 是否包含正确的动态转换机制,但是我们还没有一个 T 类型的对象来调用这个方法。这就是reinterpret_cast<T>(0)
它的用途。我们不需要实际的对象 as this
,因为编译器只需要检查成功的对象类型。相反,我们在 T 类型的空指针上调用一个方法。
I don't think this is allowed by the C++ standard, but it works since this
isn't actually used inside the method.
我认为 C++ 标准不允许这样做,但它有效,因为this
实际上并未在方法内部使用。