Ich habe Probleme, die neue Signal- / Slot-Syntax (unter Verwendung des Zeigers auf die Elementfunktion) in Qt 5 in den Griff zu bekommen, wie unter Neue Signal-Slot-Syntax beschrieben . Ich habe versucht, dies zu ändern:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
dazu:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
Beim Versuch, es zu kompilieren, wird jedoch eine Fehlermeldung angezeigt:
Fehler: Keine Übereinstimmungsfunktion für den Aufruf von
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
Ich habe es mit clang und gcc unter Linux versucht, beide mit -std=c++11
.
Was mache ich falsch und wie kann ich das beheben?
Antworten:
Das Problem hierbei ist, dass es zwei Signale mit diesem Namen gibt:
QSpinBox::valueChanged(int)
undQSpinBox::valueChanged(QString)
. Ab Qt 5.7 stehen Hilfsfunktionen zur Auswahl der gewünschten Überlastung zur Verfügung, damit Sie schreiben könnenFür Qt 5.6 und früher müssen Sie Qt mitteilen, welches Sie auswählen möchten, indem Sie es auf den richtigen Typ umwandeln:
Ich weiß, es ist hässlich . Aber daran führt kein Weg vorbei. Die heutige Lektion lautet: Überlasten Sie Ihre Signale und Slots nicht!
Nachtrag : Was an der Besetzung wirklich nervt, ist das
void
(für Signale).Daher habe ich manchmal dieses C ++ 11-Snippet verwendet:
Verwendung:
Ich persönlich finde es nicht wirklich nützlich. Ich erwarte, dass dieses Problem von selbst verschwindet, wenn Creator (oder Ihre IDE) automatisch die richtige Besetzung einfügt, wenn der Vorgang des Aufnehmens des PMF automatisch abgeschlossen wird. Aber in der Zwischenzeit ...
Hinweis: Die PMF-basierte Verbindungssyntax erfordert kein C ++ 11 !
Nachtrag 2 : In Qt 5.7 wurden Hilfsfunktionen hinzugefügt, um dies zu mildern, modelliert nach meiner obigen Problemumgehung. Der Haupthelfer ist
qOverload
(Sie haben auchqConstOverload
undqNonConstOverload
).Anwendungsbeispiel (aus den Dokumenten):
Anhang 3 : Wenn Sie sich die Dokumentation eines überlasteten Signals ansehen, ist die Lösung des Überlastungsproblems jetzt in den Dokumenten selbst klar angegeben. Zum Beispiel sagt https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1
quelle
static_cast
Hässlichkeit gegenüber der alten Syntax, einfach weil die neue Syntax eine Überprüfung der Kompilierungszeit auf das Vorhandensein des Signals / Slots ermöglicht, in dem die alte Syntax zur Laufzeit fehlschlagen würde.QSerialPort
)Die Fehlermeldung lautet:
Der wichtige Teil davon ist die Erwähnung des " ungelösten überlasteten Funktionstyps ". Der Compiler weiß nicht, ob Sie meinen
QSpinBox::valueChanged(int)
oderQSpinBox::valueChanged(QString)
.Es gibt eine Handvoll Möglichkeiten, um die Überlastung zu beheben:
Geben Sie einen geeigneten Vorlagenparameter an
connect()
Dies zwingt
connect()
dazu, sich&QSpinBox::valueChanged
in die Überlastung aufzulösen , die eine benötigtint
.Wenn Sie ungelöste Überladungen für das Slot-Argument haben, müssen Sie das zweite Template-Argument an angeben
connect()
. Leider gibt es keine Syntax, nach der der erste abgeleitet werden muss, sodass Sie beide angeben müssen. Dann kann der zweite Ansatz helfen:Verwenden Sie eine temporäre Variable des richtigen Typs
Die Zuordnung zu
signal
wählt die gewünschte Überladung aus und kann nun erfolgreich in die Vorlage eingesetzt werden. Dies funktioniert genauso gut mit dem Argument 'slot', und ich finde es in diesem Fall weniger umständlich.Verwenden Sie eine Konvertierung
Wir können dies
static_cast
hier vermeiden , da es sich lediglich um einen Zwang handelt, anstatt den Schutz der Sprache aufzuheben. Ich benutze so etwas wie:Dies ermöglicht es uns zu schreiben
quelle
Eigentlich können Sie Ihren Slot einfach mit Lambda umwickeln und dies:
wird besser aussehen. : \
quelle
Die obigen Lösungen funktionieren, aber ich habe dies auf eine etwas andere Weise mithilfe eines Makros gelöst. Nur für den Fall, dass es hier ist:
Fügen Sie dies in Ihren Code ein.
Dann Ihr Beispiel:
Wird:
quelle
#define CONNECTCAST(class,fun,args) static_cast<void(class::*)args>(&class::fun)
- wieCONNECTCAST(QSpinBox, valueChanged, (double))
in diesem Fall verwendet.