¿Cómo funciona qobject cast?
Acabo de encontrar el siguiente código en Qt y estoy un poco confundido de lo que está pasando aquí.
Especialmente en cuanto a lo que reinterpret_cast<T>(0)
hace?
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?
1 answers
Esto es un poco complicado...
Recuerde que qobject_cast<T>(obj)
es una forma de convertir dinámicamente un QObject
al tipo de destino T
que también 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; }
Así que si tienes un objeto x
de type T
y un objeto y
de type 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*
. Debido a que la función está templada con un solo parámetro de tipo, los tipos T
y U
deben ser los mismos.
Ahora, si llamas a x->qt_check_for_QOBJECT_macro(x)
entonces debes esperar que los tipos sean los mismos y que la compilación tenga éxito trivialmente. Sin embargo, recuerde que this
tiene el mismo tipo que la clase en la que se definió el método. Así que si x
es de una clase que era derivado de T pero no contiene su propia definición de qt_check_for_QOBJECT_macro
, la llamada fallará.
Así que tenemos una manera de comprobar si el tipo de destino T contiene el mecanismo correcto para el lanzamiento dinámico, pero no tenemos un objeto de tipo T para llamar a este método todavía. Para eso está el reinterpret_cast<T>(0)
. No necesitamos un objeto real como this
, ya que el compilador solo necesita los tipos de objetos para que la comprobación tenga éxito. En su lugar, llamamos a un método sobre un puntero nulo de tipo T.
No creo que esto sea permitido por el estándar de C++, pero funciona ya que this
no se usa realmente dentro del método.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-31 04:32:27