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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:37:57  来源:igfitidea点击:

How does qobject_cast work?

c++qtcastingreinterpret-caststatic-cast

提问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 QObjectto the target type Twhich also derives from QObject. Now, for this to work, the macro Q_OBJECTshould 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_macrocall 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 xof type Tand an object yof type U, the call x->qt_check_for_QOBJECT_macro(y)calls the function qYouForgotTheQ_OBJECT_Macrowith parameters of types T*and U*. Because the function is templated with a single type parameter, the types Tand Umust be the same.

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

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 thishas the same type as the class the method was defined in. So if xis 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 thisisn't actually used inside the method.

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