Différences entre les connexions basées sur les chaînes de caractères et celles basées sur les foncteurs
Qt offre deux façons différentes d'écrire des connexions signal-emplacement en C++ : La syntaxe de connexion basée sur les chaînes de caractères et la syntaxe de connexion basée sur les foncteurs. Les deux syntaxes présentent des avantages et des inconvénients. Le tableau ci-dessous résume leurs différences.
| Basée sur une chaîne de caractères | Basée sur un foncteur | |
|---|---|---|
| La vérification de type est effectuée à... | au moment de l'exécution | Au moment de la compilation |
| Peut effectuer des conversions de type implicites | Y | |
| Peut connecter des signaux à des expressions lambda | Y | |
| Possibilité de connecter des signaux à des slots qui ont plus d'arguments que le signal (en utilisant des paramètres par défaut) | Y | |
| Possibilité de connecter des fonctions C++ à des fonctions QML | Y |
Les sections suivantes expliquent ces différences en détail et montrent comment utiliser les caractéristiques propres à chaque syntaxe de connexion.
Vérification de type et conversions de type implicites
Les connexions basées sur des chaînes de caractères vérifient le type en comparant les chaînes au moment de l'exécution. Cette approche présente trois limites :
- Les erreurs de connexion ne peuvent être détectées qu'après le début de l'exécution du programme.
- Les conversions implicites ne peuvent pas être effectuées entre les signaux et les slots.
- Les typedefs et les espaces de noms ne peuvent pas être résolus.
Les limitations 2 et 3 existent parce que le comparateur de chaînes de caractères n'a pas accès aux informations sur les types C++, et qu'il s'appuie donc sur la correspondance exacte des chaînes de caractères.
En revanche, les connexions basées sur les foncteurs sont vérifiées par le compilateur. Le compilateur détecte les erreurs au moment de la compilation, autorise les conversions implicites entre types compatibles et reconnaît les différents noms d'un même type.
Par exemple, seule la syntaxe basée sur les foncteurs peut être utilisée pour connecter un signal qui transporte une valeur int à un slot qui accepte une valeur double. Une valeur QSlider contient une valeur int tandis qu'une valeur QDoubleSpinBox contient une valeur double. L'extrait suivant montre comment les synchroniser :
auto slider = new QSlider(this); auto doubleSpinBox = new QDoubleSpinBox(this); // OK: The compiler can convert an int into a double connect(slider, &QSlider::valueChanged, doubleSpinBox, &QDoubleSpinBox::setValue); // ERROR: The string table doesn't contain conversion information connect(slider, SIGNAL(valueChanged(int)), doubleSpinBox, SLOT(setValue(double)));
L'exemple suivant illustre l'absence de résolution de noms. QAudioInput::stateChanged() est déclaré avec un argument de type "QAudio::State". Ainsi, les connexions basées sur des chaînes de caractères doivent également spécifier "QAudio::State", même si "State" est déjà visible. Ce problème ne s'applique pas aux connexions basées sur des foncteurs, car les types d'arguments ne font pas partie de la connexion.
auto audioInput = new QAudioInput(QAudioFormat(), this); auto widget = new QWidget(this); // OK connect(audioInput, SIGNAL(stateChanged(QAudio::State)), widget, SLOT(show())); // ERROR: The strings "State" and "QAudio::State" don't match using namespace QAudio; connect(audioInput, SIGNAL(stateChanged(State)), widget, SLOT(show())); // ...
Établir des connexions avec des expressions lambda
La syntaxe de connexion basée sur un foncteur permet de connecter des signaux à des expressions lambda, qui sont en fait des slots inline. Cette fonctionnalité n'est pas disponible avec la syntaxe basée sur les chaînes de caractères.
Dans l'exemple suivant, la classe TextSender émet un signal textCompleted() qui porte un paramètre QString. Voici la déclaration de la classe :
class TextSender : public QWidget { Q_OBJECT QLineEdit *lineEdit; QPushButton *button; signals: void textCompleted(const QString& text) const; public: TextSender(QWidget *parent = nullptr); };
Voici la connexion qui émet TextSender::textCompleted() lorsque l'utilisateur clique sur le bouton :
TextSender::TextSender(QWidget *parent) : QWidget(parent) { lineEdit = new QLineEdit(this); button = new QPushButton("Send", this); connect(button, &QPushButton::clicked, [=] { emit textCompleted(lineEdit->text()); }); // ... }
Dans cet exemple, la fonction lambda a simplifié la connexion même si QPushButton::clicked() et TextSender::textCompleted() ont des paramètres incompatibles. En revanche, une implémentation basée sur des chaînes de caractères nécessiterait un code de base supplémentaire.
Remarque : la syntaxe de connexion basée sur les foncteurs accepte les pointeurs vers toutes les fonctions, y compris les fonctions autonomes et les fonctions membres ordinaires. Toutefois, pour des raisons de lisibilité, les signaux ne doivent être connectés qu'aux slots, aux expressions lambda et aux autres signaux.
Connecter des objets C++ à des objets QML
La syntaxe basée sur les chaînes de caractères peut connecter des objets C++ à des objets QML, mais pas la syntaxe basée sur les foncteurs. En effet, les types QML sont résolus à l'exécution et ne sont donc pas disponibles pour le compilateur C++.
Dans l'exemple suivant, en cliquant sur l'objet QML, l'objet C++ imprime un message, et vice-versa. Voici le type QML (en QmlGui.qml) :
Rectangle { width: 100; height: 100 signal qmlSignal(string sentMsg) function qmlSlot(receivedMsg) { console.log("QML received: " + receivedMsg) } MouseArea { anchors.fill: parent onClicked: qmlSignal("Hello from QML!") } }
Voici la classe C++ :
class CppGui : public QWidget { Q_OBJECT QPushButton *button;signals: void cppSignal(const QVariant& sentMsg) const;public slots: void cppSlot(const QString& receivedMsg) const { qDebug() << "C++ received:" << receivedMsg; }public: CppGui(QWidget *parent = nullptr) : QWidget(parent) { button = new QPushButton("Click Me !", this) ; connect(button, &QPushButton::clicked, [=] { emit cppSignal("Hello from C++ !") ; }) ; } } ;
Voici le code qui établit les connexions entre les signaux et les fentes :
auto cppObj = new CppGui(this); auto quickWidget = new QQuickWidget(QUrl("QmlGui.qml"), this); auto qmlObj = quickWidget->rootObject(); // Connect QML signal to C++ slot connect(qmlObj, SIGNAL(qmlSignal(QString)), cppObj, SLOT(cppSlot(QString))); // Connect C++ signal to QML slot connect(cppObj, SIGNAL(cppSignal(QVariant)), qmlObj, SLOT(qmlSlot(QVariant)));
Remarque : toutes les fonctions JavaScript en QML prennent des paramètres de type var, qui correspond au type QVariant en C++, sauf si elles utilisent des annotations de type. Voir Invocation des méthodes QML pour plus de détails.
Lorsque l'on clique sur le site QPushButton, la console affiche "QML reçu : "Hello from C++ !"". De même, lorsque l'on clique sur le rectangle, la console affiche "C++ received : "Hello from QML !"".
Voir Interagir avec les objets QML à partir de C++ pour d'autres façons de permettre aux objets C++ d'interagir avec les objets QML.
Utilisation de paramètres par défaut dans les slots pour se connecter à des signaux avec moins de paramètres
En général, une connexion ne peut être établie que si le slot a le même nombre d'arguments que le signal (ou moins), et si tous les types d'arguments sont compatibles.
La syntaxe de connexion basée sur les chaînes de caractères permet de contourner cette règle : si le slot a des paramètres par défaut, ces paramètres peuvent être omis dans le signal. Lorsque le signal est émis avec moins d'arguments que le slot, Qt exécute le slot en utilisant les valeurs des paramètres par défaut.
Les connexions basées sur un foncteur ne supportent pas cette fonctionnalité.
Supposons qu'il y ait une classe appelée DemoWidget avec un slot printNumber() qui a un argument par défaut :
public slots: void printNumber(int number = 42) { qDebug() << "Lucky number" << number; }
En utilisant une connexion basée sur une chaîne de caractères, DemoWidget::printNumber() peut être connecté à QApplication::aboutToQuit(), même si ce dernier n'a pas d'arguments. La connexion basée sur un foncteur produira une erreur de compilation :
DemoWidget::DemoWidget(QWidget *parent) : QWidget(parent) { // OK : printNumber() sera appelé avec une valeur par défaut de 42 connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(printNumber())) ; // ERREUR : Le compilateur exige des arguments compatibles connect(qApp, &QCoreApplication::aboutToQuit, this, &DemoWidget::printNumber) ; }
Pour contourner cette limitation avec la syntaxe basée sur les foncteurs, connectez le signal à une fonction lambda qui appelle le slot. Voir la section ci-dessus, Établir des connexions avec des expressions lambda.
Sélection de signaux et de slots surchargés
Avec la syntaxe basée sur les chaînes de caractères, les types de paramètres sont explicitement spécifiés. Par conséquent, l'instance souhaitée d'un signal surchargé ou d'un slot n'est pas ambiguë.
En revanche, avec la syntaxe basée sur les foncteurs, vous devez spécifier explicitement la version d'un signal surchargé ou d'un slot à laquelle vous souhaitez vous connecter.
Par exemple, QLCDNumber possède trois versions du slot display():
QLCDNumber::display(int)QLCDNumber::display(double)QLCDNumber::display(QString)
Pour connecter la version int à QSlider::valueChanged(), les deux syntaxes sont les suivantes :
auto slider = new QSlider(this); auto lcd = new QLCDNumber(this); // String-based syntax connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int))); // Functor-based syntax connect(slider, &QSlider::valueChanged, lcd, qOverload<int>(&QLCDNumber::display));
Pour des exemples complets de connexion à des signaux surchargés et à des slots à l'aide de qOverload(), static_cast et lambdas, voir Connecting to Overloaded Signals and Slots (Connexion à des signaux surchargés et à des slots).
Voir également qOverload().
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.