Qt "Private Slots": Was ist das?

83

Ich verstehe, wie man es benutzt, aber die Syntax stört mich. Was macht "Private Slots:"?

Ich habe noch nie etwas zwischen dem privaten Schlüsselwort und dem: in einer Klassendefinition gesehen. Gibt es hier ausgefallene C ++ - Magie?

Und hier ein Beispiel:

 #include <QObject>

 class Counter : public QObject
 {
     Q_OBJECT

 public:
     Counter() { m_value = 0; }

     int value() const { return m_value; }

 public slots:
     void setValue(int value);

 ...
Justin
quelle
3
Dies ist kein Standard C ++. Dies ist ein QT-Framework-Konstrukt. Suchen Sie nach QT-Signalen und Slots .
Alok Save
1
Beim Kompilieren wird als C ++ slotsdefiniert als #define slots. Beim Kompilieren mit Qt MOC wird Code für den C ++ - Compiler generiert.
dalle
2
lol das war noch schwieriger für mich zu verstehen, weil ich C ++ so lange nicht mehr benutzt habe, ich dachte, sie haben etwas Neues hinzugefügt
dtc

Antworten:

57

Slots sind eine Qt-spezifische Erweiterung von C ++. Es wird erst kompiliert, nachdem der Code über den Präprozessor von Qt, den Meta-Object Compiler (moc), gesendet wurde. Dokumentation finden Sie unter http://doc.qt.io/qt-5/moc.html .

Bearbeiten: Wie Frank betont, wird moc nur zum Verknüpfen benötigt. Die zusätzlichen Schlüsselwörter werden mit dem Standardpräprozessor #definiert.

Russell Davis
quelle
Danke, Qts Präprozessor ist das, was mir in meinem mentalen Modell von dem, was vor sich ging, gefehlt hat.
Justin
16
Nicht korrekt, der Code wird ständig kompiliert, da "Signale" und "Slots" leere Definitionen sind, sodass der Compiler sie nie sieht. Diese Makros sind Hinweise für moc, das zusätzlichen Code generiert . Die ursprünglichen .h- und .cpp-Dateien werden nicht geändert und können ohne moc problemlos kompiliert werden. Was fehlschlagen würde, ist die Verknüpfung, da die von moc generierten Definitionen (Signaldefinitionen, Metaobjekt usw.) ansonsten fehlen.
Frank Osterfeld
1
Ist das slotsSchlüsselwort notwendig? Ich habe versucht, ein paar winzige Qt-Programme zu kompilieren / zu verknüpfen, die Slots ohne das slotsSchlüsselwort aufrufen, und sie haben sich gut entwickelt. Meine Experimente zeigen, dass: signals:definitiv notwendig ist, slotsmöglicherweise unnötig ist und emitunnötig zu sein scheint, wie ich an anderer Stelle gelesen habe.
Es ist Ihre App LLC
2
slotsist in Qt5 nicht erforderlich. Qt hat die connect()Syntax aktualisiert , um das Verbinden eines Signals mit einer beliebigen Funktion, einschließlich Lambdas, zu ermöglichen. Aus diesem Grund slotsist nicht notwendig. Das slotsSchlüsselwort wirkt sich jedoch weiterhin auf die Art und Weise aus, wie ein Objekt erstellt QMetaObjectwird. moc(auch bekannt als "Metaobjekt-Compiler") erkennt eine Methode nur dann als Slot, wenn sie sich im slots:Abschnitt einer Klassendefinition befindet. Obwohl die Verbindung weiterhin funktioniert, wird die Methode in Introspection-Tools nicht angezeigt.
Chris
19

Die Schlüsselwörter wie public, privatewerden für Qt-Slots ignoriert. Alle Slots sind tatsächlich öffentlich und können verbunden werden

Andrew
quelle
31
Wenn die Methode über einen Signal- / Slot-Mechanismus aufgerufen wird, werden die Zugriffsspezifizierer ignoriert. Slots sind aber auch "normale" Methoden. Wenn Sie sie auf herkömmliche Weise aufrufen, werden die Zugriffsspezifizierer berücksichtigt.
Borges
4
@borges und zukünftige Leser. In Qt5 kann die connect () -Methode Funktionszeiger verwenden (was Vorteile hat). Wenn Sie eine Verbindung mit Funktionszeigern herstellen, werden die Zugriffsspezifizierer im Signal- / Slot-Mechanismus erzwungen.
Tod
3
@borges Ich glaube das ist falsch oder zumindest war die Erklärung unklar. Die Zugriffsspezifizierer schränken Ihre Fähigkeit, Signale an Steckplätze anzuschließen, nicht ein. Das heißt, ein privater Steckplatz kann mit jedem Signal verbunden werden. Der Zugriffsspezifizierer schützt die Elementfunktion jedoch (auf typische Weise) vor ihrer Klasse, während sie aufgerufen wird. Die Zugriffsspezifizierer werden also nicht "ignoriert", wenn sie über den Signal- / Steckplatzmechanismus aufgerufen werden: Sie haben keinen Einfluss auf die Verbindung von Steckplätzen mit Signalen, schützen jedoch die Funktion vor thisder uns bekannten Art und Weise.
Es ist Ihre App LLC
4

Wenn Sie Slots als privat deklarieren, können Sie sie nicht wie bei jeder anderen Methode aus einem Kontext referenzieren, in dem sie privat sind. Folglich können Sie die Adresse für private Slots nicht an übergeben connect.

Wenn Sie das Signal als privat deklarieren, sagen Sie, dass nur diese Klasse es verwalten kann, Funktionselementzeiger jedoch keine Zugriffsbeschränkungen haben :

class A{
    private:
    void e(){

    }
    public:
    auto getPointer(){
        return &A::e;   
    }
};

int main()
{
    A a;
    auto P=a.getPointer();
    (a.*P)();
}

Abgesehen davon gilt auch, was andere Antworten erwähnen:
- Sie können immer noch private Signale und Slots von außen mit Tricks verbinden
- signalsund slotssind leere Makros und brechen nicht den Sprachstandard

Euri Pinhollow
quelle
Warum hat diese Frage keine positiven Stimmen? Stimmt etwas nicht? Ich finde die Aussage, dass slotsein Makro hilfreich ist. Ich kann keine privaten Slot-Funktionszeiger connectohne Tricks verbinden, oder?
Arch Linux Tux
@ArchLinuxTux- Funktionselementzeiger unterliegen keinen Zugriffsbeschränkungen .
Euri Pinhollow