====== Signale und Slots ======
Wer schonmal mit QT gearbeitet hat, dem sind Signale und Slots natürlich ein Begriff. Neben den grundlegenden Dingen wie dem Q_OBJECT-Makro gibt es
jedoch in einigen Fällen noch ein paar weitere Dinge zu beachten.
===== Vererbung =====
Bei normaler Vererbung gibt es kein Problem - einfach behandeln wie sonst auch. Aber es gibt Fälle, in denen man um Mehrfachvererbung nicht rumkommt. Klassisches
Beispiel ist die Verwendung von Interfaces.
Man nehme ein einfaches Beispiel (welches natürlich auch anders gelöst werden könnte) - eine Resourcen-Pipeline. Man benötigt also:
* Eingänge / Quellen
* Prozessoren
* Ausgänge / Senken
Nun soll es möglich sein, eine Kette Quelle - Prozessor1 - ... - ProzessorN - Senke zu erzeugen. Es bietet sich hierbei an, Signale "output" und Slots "input"
zu definieren, dann kann die Kette einfach mit
connect(source,SIGNAL(output(..)),processor1,SLOT(input(..)));
usw. erzeugt werden. Soweit so gut. Allerdings wäre es ja auch schön, wenn man einfach nur
connect(source,processor1)
schreiben könnte. Genau genommen, ist ein Prozessor ja auch garnichts anderes als gleichzeitig **Quelle** und **Senke**.
Damit würde das oben genannte aber funktionieren, etwa so:
void connect(Source *a, Sink *b){
connect(a,SIGNAL(output(...)),b,SLOT(input(...)));
}
Alles zusammengenommen wäre es also wünschenswert, ein Basisklasse oder noch genauer ein Interface Quelle zu haben, welche das Signal "output"
erzwingt und ein Interface, welche den Slot "input" erzwingt.
Nun ist es aber so, dass man nicht mehrfach von QObject erben kann - ich habe deshalb keine Möglichkeit gefunden, oben gesetzte Ziele (also das erzwingen
von Signals/Slots) vollständig zu erreichen. Was man aber machen kann ist folgendes:
class Source{
protected:
void output(...)=0;
};
class Sink
protected:
void input(...)=0;
};
Das funktioniert insofern, als die abgeleiteten Klassen zumindest output bzw. input implementieren *müssen*. Insbesondere kann output dabei als Signal deklariert
werden:
class Processor:public QObject, public Sink, public Source{
Q_OBJECT
...
public slots:
void input(...);
public signals:
void output(...);
};
void Processor::input(...){
...
emit output(...);
}
Allerdings muss zudem die oben erstellte connect noch leicht geändert werden:
void connect(Source *a, Sink *b){
connect(dynamic_casta,SIGNAL(output(...)),dynamic_castb,SLOT(input(...)));
}