¿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?

Author: troyane, 2010-12-23

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.

 37
Author: Amnon,
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