Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
160 views
in Technique[技术] by (71.8m points)

c++ - How does qobject_cast work?

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?

question from:https://stackoverflow.com/questions/4518163/how-does-qobject-cast-work

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...