c++ - dynamic_cast - ¿Cómo funciona qobject_cast?
cast c++ (1)
Esto es un poco complicado ...
Recuerde que qobject_cast<T>(obj)
es una forma de lanzar dinámicamente un QObject
al tipo de destino T
que también se deriva de QObject
. Ahora, para que esto funcione, la macro Q_OBJECT
debe incluirse en la definición de clase T
Aparentemente, la llamada qt_check_for_QOBJECT_macro
es para comprobar que la clase realmente contiene la macro Q_OBJECT. Cuando la macro se expande, contiene las siguientes definiciones:
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; }
Entonces, si tiene un objeto x
de tipo T
y un objeto y
de tipo U
, la llamada x->qt_check_for_QOBJECT_macro(y)
llama a la función qYouForgotTheQ_OBJECT_Macro
con parámetros de tipos T*
y U*
. Como la función se modela con un solo parámetro de tipo, los tipos T
y U
deben ser iguales.
Ahora, si llama a x->qt_check_for_QOBJECT_macro(x)
entonces debe esperar que los tipos sean los mismos y que la compilación tenga éxito trivial. Sin embargo, recuerde que tiene el mismo tipo que la clase en la que se definió el método. Por lo tanto, si x
es de una clase derivada de T pero no contiene su propia definición de qt_check_for_QOBJECT_macro
, la llamada fallará.
Entonces, tenemos una forma de verificar si el tipo de destino T contiene el mecanismo correcto para el lanzamiento dinámico, pero no tenemos un objeto de tipo T para invocar este método aún. Para eso es reinterpret_cast<T>(0)
. No necesitamos un objeto real como this
, ya que el compilador solo necesita los tipos de objeto para que la verificación tenga éxito. En cambio, llamamos a un método en un puntero nulo de tipo T.
No creo que esto esté permitido por el estándar de C ++, pero funciona, ya que this
no se usa realmente dentro del método.
Acabo de encontrar el siguiente código en Qt y estoy un poco confundido de lo que está sucediendo aquí.
Especialmente en lo que hace 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))));
}
¿Alguien quiere explicar?