Comment fonctionne QObject cast?

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

Surtout à 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 veut vous expliquer?

38
demandé sur troyane 2010-12-23 14:02:39

1 réponses

C'est un peu compliqué...

Souviens-toi de ça qobject_cast<T>(obj) est un moyen de lancer dynamiquement un QObject au type cible {[3] } qui dérive également de QObject. Maintenant, pour que cela fonctionne, la macro Q_OBJECT devrait être incluse dans la définition de la classe T.

Apparemment, l'appel qt_check_for_QOBJECT_macro sert à vérifier que la classe contient vraiment 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 de x->qt_check_for_QOBJECT_macro(y) appelle la fonction qYouForgotTheQ_OBJECT_Macro, avec les paramètres de types T* et U*. Étant donné que 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, rappelez - vous que this a le même type que la classe dans laquelle la méthode a été définie. Donc, si x est d'une classe qui était dérivée de T, mais 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 la distribution dynamique, mais nous n'avons pas encore d'objet de type T pour appeler cette méthode. C'est à ça que sert le reinterpret_cast<T>(0). 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 null de type T.

Je ne pense pas que ce soit autorisé par le standard C++, mais cela fonctionne puisque this n'est pas réellement utilisé dans la méthode.

37
répondu Amnon 2015-08-31 04:32:27