Designfrage: Alternative zu template-Klassen bei QObject
Verfasst: 12. Juni 2013 10:45
Moin,
wenn man signals/slots verwenden möchte, muss bekanntlich von QObject geerbt werden. Leider kann moc aber nicht mit von QObject geerbten template Klassen umgehen. Folgendes geht also z.B. nicht:
Leider funktionieren virtuelle Signale ebenfalls nicht, folgende Deklaration ist also auch falsch:
Ich habe nun folgendes Problem. Ich habe eine Basisklasse Adapter und eine Basisklasse Job:
Schön wäre, wenn ich hier die konkrete abgeleitete Klassen im Signal senden könnte. Klar kann ich das, aber der Empfänger muss dann ja korrekt casten, was ich unschön (und fehleranfällig) finde. Da das signal aber nicht virtual sein darf, sehe ich hier keine andere Möglichkeit.
Richtig unschön wird es aber erst jetzt. Eine abgeleitete Klasse eines Adapter könnte so aussehen:
Und natürlich muss ich jetzt 5 verschiedene Job Klassen haben. Das Problem ist nur, das ich etwa 100 verschiedene Adapter implementieren muss, also 500 verschiedene Jobs definieren müsste.
Der TodoFetchJob sieht übrigens etwa so aus:
Das schöne an diesem TodoListJob ist, das der Benutzer nicht casten muss, die Verwendung dieser Klasse also leichter ist. Wenn ich templates verwenden könnte, wäre der Aufwand für mich auch nicht allzu hoch. Ich würde 5 Job-Klassen (List, Fetch, Create, Update und Remove) haben, die mittels Template-Parameter den richtigen Typ hätten. Da ich aber signals/slots verwenden möchte, geht das leider nicht.
Ich stolpere hier also gerade über "alle" Probleme von moc: Keine virtuellen Signale, keine Templates, keine Mehrfachvererbung von QObject (hier nicht angesprochen, wurde aber die Implementierung der Jobs deutlich erleichtern).
Wie könnte ich mir diesen Aufwand ersparen, ohne das die API für den Benutzer wesentlich komplizierter wird? Oder ist das Design so grundsätzlich total daneben?
MfG,
Stefan
wenn man signals/slots verwenden möchte, muss bekanntlich von QObject geerbt werden. Leider kann moc aber nicht mit von QObject geerbten template Klassen umgehen. Folgendes geht also z.B. nicht:
Code: Alles auswählen
template <class T>
class Foo : public QObject
{
//...
signals:
void finished(const T *value);
Code: Alles auswählen
signals:
virtual void finished(const BaseClass *value);Code: Alles auswählen
class Adapter : public QObject
{
//...
};Code: Alles auswählen
class Job : public QObject
{
//...
signals:
void finished(Job *job);
};Richtig unschön wird es aber erst jetzt. Eine abgeleitete Klasse eines Adapter könnte so aussehen:
Code: Alles auswählen
class TodoAdapter : public Adapter
{
Q_OBJECT
Q_DISABLE_COPY( TodoAdapter )
public:
//...
virtual TodoListJob* list() = 0;
virtual TodoFetchJob* fetch(const QByteArray &id) = 0;
virtual TodoCreateJob* create(Document::Todo *value) = 0;
virtual TodoUpdateJob* update(Document::Todo *value) = 0;
virtual TodoRemoveJob* remove(Document::Todo *value) = 0;
};Der TodoFetchJob sieht übrigens etwa so aus:
Code: Alles auswählen
class TodoListJob : public Job
{
Q_OBJECT
Q_DISABLE_COPY( TodoListJob )
public:
virtual QList<QSharedPointer<Document::Todo>> result() const = 0;
signals:
void processed(QSharedPointer<Document::Todo> value);
};Ich stolpere hier also gerade über "alle" Probleme von moc: Keine virtuellen Signale, keine Templates, keine Mehrfachvererbung von QObject (hier nicht angesprochen, wurde aber die Implementierung der Jobs deutlich erleichtern).
Wie könnte ich mir diesen Aufwand ersparen, ohne das die API für den Benutzer wesentlich komplizierter wird? Oder ist das Design so grundsätzlich total daneben?
MfG,
Stefan