39 votes

Comment fonctionne qobject_cast ?

Je viens de trouver le code suivant dans Qt et je suis un peu confus de ce qui se passe ici.

Surtout en ce qui concerne ce que reinterpret_cast<T>(0) fait ?

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))));
}

Quelqu'un peut expliquer ?

38voto

Amnon Points 4864

C'est un peu compliqué...

Rappelez-vous que qobject_cast<T>(obj) est un moyen d'intégrer dynamiquement un QObject au type cible T qui dérive également de QObject . Maintenant, pour que cela fonctionne, la macro Q_OBJECT doit être incluse dans la définition de la classe T .

Apparemment, le qt_check_for_QOBJECT_macro permet de vérifier que la classe contient bien la macro Q_OBJECT. Lorsque la macro est développée, elle contient les définitions suivantes :

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; }

Donc si vous avez un objet x de type T et un objet y de type U l'appel x->qt_check_for_QOBJECT_macro(y) appelle la fonction qYouForgotTheQ_OBJECT_Macro avec des paramètres de type T* et U* . Comme la fonction est modélisée avec un seul paramètre de type, les types T et U doivent être les mêmes.

Maintenant, si vous appelez x->qt_check_for_QOBJECT_macro(x) alors vous devriez vous attendre à ce que les types soient les mêmes et que la compilation réussisse trivialement. Cependant, n'oubliez pas que this a le même type que la classe dans laquelle la méthode a été définie. Ainsi, si x est d'une classe qui a été dérivée de T mais qui ne contient pas sa propre définition de qt_check_for_QOBJECT_macro l'appel échouera.

Nous avons donc un moyen de vérifier si le type cible T contient le mécanisme correct pour le cast dynamique, mais nous n'avons pas encore d'objet de type T sur lequel appeler cette méthode. C'est ce que la méthode reinterpret_cast<T>(0) est pour. Nous n'avons pas besoin d'un objet réel comme this puisque le compilateur n'a besoin que des types d'objets pour que la vérification réussisse. Au lieu de cela, nous appelons une méthode sur un pointeur nul de type T.

Je ne pense pas que cela soit autorisé par la norme C++, mais cela fonctionne puisque this n'est pas réellement utilisé à l'intérieur de la méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X