J'ai du mal à me familiariser avec la nouvelle syntaxe de signal / slot (en utilisant le pointeur vers la fonction membre) dans Qt 5, comme décrit dans la nouvelle syntaxe de slot de signal . J'ai essayé de changer ceci:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
pour ça:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
mais j'obtiens une erreur lorsque j'essaye de le compiler:
erreur: pas de fonction correspondante pour l'appel à
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
J'ai essayé avec clang et gcc sous Linux, les deux avec -std=c++11
.
Qu'est-ce que je fais mal et comment puis-je y remédier?
Réponses:
Le problème ici est qu'il y a deux signaux avec ce nom:
QSpinBox::valueChanged(int)
etQSpinBox::valueChanged(QString)
. À partir de Qt 5.7, des fonctions d'assistance sont fournies pour sélectionner la surcharge souhaitée, vous pouvez donc écrirePour Qt 5.6 et les versions antérieures, vous devez indiquer à Qt celui que vous voulez choisir, en le castant dans le bon type:
Je sais, c'est moche . Mais il n'y a aucun moyen de contourner cela. La leçon d'aujourd'hui est la suivante: ne surchargez pas vos signaux et vos slots!
Addendum : ce qui est vraiment ennuyeux avec le casting, c'est que
void
(pour les signaux).Je me suis donc retrouvé à utiliser parfois cet extrait de code C ++ 11:
Usage:
Personnellement, je le trouve pas vraiment utile. Je m'attends à ce que ce problème disparaisse de lui-même lorsque Creator (ou votre IDE) insérera automatiquement la bonne distribution lors de la finalisation automatique de l'opération de prise du PMF. Mais en attendant ...
Remarque: la syntaxe de connexion basée sur PMF ne nécessite pas C ++ 11 !
Addendum 2 : dans Qt 5.7, des fonctions d'assistance ont été ajoutées pour atténuer ce problème, sur le modèle de ma solution de contournement ci-dessus. L'assistant principal est
qOverload
(vous avez aussiqConstOverload
etqNonConstOverload
).Exemple d'utilisation (à partir de la documentation):
Addendum 3 : si vous regardez la documentation de tout signal surchargé, la solution au problème de surcharge est maintenant clairement indiquée dans la documentation elle-même. Par exemple, https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 dit
la source
static_cast
laideur à l'ancienne syntaxe, simplement parce que la nouvelle syntaxe permet une vérification à la compilation de l'existence du signal / slot où l'ancienne syntaxe échouerait à l'exécution.QSerialPort
)Le message d'erreur est:
La partie importante de ceci est la mention du « type de fonction surchargé non résolu ». Le compilateur ne sait pas si vous voulez dire
QSpinBox::valueChanged(int)
ouQSpinBox::valueChanged(QString)
.Il existe plusieurs façons de résoudre la surcharge:
Fournissez un paramètre de modèle approprié pour
connect()
Cela oblige
connect()
à résoudre&QSpinBox::valueChanged
la surcharge qui prend unint
.Si vous avez des surcharges non résolues pour l'argument slot, vous devrez fournir le deuxième argument de modèle à
connect()
. Malheureusement, il n'y a pas de syntaxe pour demander que le premier soit déduit, vous devrez donc fournir les deux. C'est alors que la deuxième approche peut aider:Utilisez une variable temporaire du type correct
L'affectation à
signal
sélectionnera la surcharge souhaitée, et maintenant elle peut être remplacée avec succès dans le modèle. Cela fonctionne aussi bien avec l'argument «slot», et je le trouve moins encombrant dans ce cas.Utiliser une conversion
Nous pouvons éviter
static_cast
ici, car il s'agit simplement d'une contrainte plutôt que d'un retrait des protections de la langue. J'utilise quelque chose comme:Cela nous permet d'écrire
la source
En fait, vous pouvez simplement envelopper votre slot avec lambda et ceci:
sera meilleure. : \
la source
Les solutions ci-dessus fonctionnent, mais j'ai résolu cela d'une manière légèrement différente, en utilisant une macro, donc juste au cas où la voici:
Ajoutez ceci dans votre code.
Ensuite, votre exemple:
Devient:
la source
#define CONNECTCAST(class,fun,args) static_cast<void(class::*)args>(&class::fun)
-à- dire - utilisé commeCONNECTCAST(QSpinBox, valueChanged, (double))
dans ce cas.