Comment Qt implémente-t-il les signaux et les slots?

Quelqu'un peut-il m'expliquer l'idée de base de Qt signals&slots mechanism IMPLEMENTATION? Je veux savoir ce que font toutes ces macros Q_OBJECT "en C++". Cette question ne concerne pas les signaux et l'utilisation des machines à sous.

, a ajouté: Je sais que Qt utilise le compilateur moc pour transformer Qt-C++ en C++simple. Mais que fait le moc? J'ai essayé de lire "moc_filename.cpp "mais je n'ai aucune idée de ce que peut quelque chose comme ça signifie

void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
    return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
15
demandé sur River 2010-01-05 20:57:51

3 réponses

en ce qui concerne les signaux et les fentes, la macro Q_OBJECT ajoute une fonction virtuelle qt_metacall() déclaration dans la déclaration de la classe qui doit être définie ultérieurement par le moc . (Il ajoute également quelques déclarations pour la conversion, mais ce n'est pas trop important ici.)

le moc lit alors le fichier d'en-tête et quand il voit la macro, il génère un autre .cpp fichier nommé moc_headerfilename.cpp avec les définitions des fonctions virtuelles et vous a demandé pourquoi vous pouvez vous en sortir avec l'évocation du signals: dans votre fichier d'en-tête sans une définition correcte des signaux.

ainsi, lorsqu'un signal est appelé, la définition du fichier mocfile est exécutée et QMetaObject::activate() est appelé avec le nom du signal et les arguments du signal. La fonction activate() calcule alors les connexions qui ont été établies et récupère les noms des emplacements appropriés.

puis il appelle qt_metacall avec les noms de fente et les arguments donnés au signal et la fonction metacall délègue ceci avec l'aide d'un grand switch - case déclaration aux fentes réelles.

comme il n'y a pas d'information d'exécution réelle possible en C++ concernant les noms réels des signaux et des slots, comme cela a déjà été remarqué, ceux-ci seront encodés par les macros SIGNAL et SLOT à simple const char* s (avec soit "1" ou "2" ajoutés au nom pour distinguer les signaux des fentes).

comme défini dans qobjectdefs.h :

#define SLOT(a)     "1"#a
#define SIGNAL(a)   "2"#a

-

l'autre chose que fait la macro Q_OBJECT est de définir les fonctions tr() à l'intérieur de votre objet qui peuvent être utilisées pour traduire votre application.

Modifier Comme vous l'avez demandé à ce que le qt_metacast est en train de faire. Il vérifie si un objet appartient à une certaine classe et si elle renvoie le pointeur vers elle. Si ce n'est pas le cas, il retourne 0.

Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);

ceci est nécessaire pour fournir une certaine réflexion d'exécution qui n'est pas possible autrement. La fonction est appelée dans QObject::inherits(const char *) par exemple et vérifie simplement pour l'héritage.

16
répondu Debilski 2014-11-25 19:56:27

ces macros ne font absolument rien "en C++ simple, - elles s'étendent à des chaînes vides (je pense).

QT utilise un compilateur de méta-objets, qui génère du code C++ pour les classes compatibles avec Q_OBJECT (implémentant les signaux/slots que vous définissez, entre autres choses).

vous pouvez lire plus à ce sujet dans le documentation officielle .

3
répondu shylent 2017-11-14 17:12:37

L'idée de base est que vous pouvez connecter vos objets leur permettant d'exécuter une méthode (slot) lorsqu'un signal est fait.

connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))

en faisant la connexion ci-dessus, quand le pistolet émet le signal, le coureur exécute sa fente.

pour ce faire, vous devez déclarer vos signaux et slots dans vos classes respectives.

Est l'idée de base.

bonne chance!

-1
répondu Drewen 2010-01-05 19:10:45