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?
This is a little complicated…
Remember that
qobject_cast<T>(obj)is a way to dynamically cast aQObjectto the target typeTwhich also derives fromQObject. Now, for this to work, the macroQ_OBJECTshould be included in the definition of classT.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:So if you have an object
xof typeTand an objectyof typeU, the callx->qt_check_for_QOBJECT_macro(y)calls the functionqYouForgotTheQ_OBJECT_Macrowith parameters of typesT*andU*. Because the function is templated with a single type parameter, the typesTandUmust 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 thatthishas the same type as the class the method was defined in. So ifxis 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
thisisn’t actually used inside the method.