Designfrage: Alternative zu template-Klassen bei QObject

Alles rund um die Programmierung mit Qt
Antworten
hilefoks
Beiträge: 144
Registriert: 13. März 2008 16:09

Designfrage: Alternative zu template-Klassen bei QObject

Beitrag von hilefoks »

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:

Code: Alles auswählen

template <class T>
class Foo : public QObject
{
    //...
    signals:
        void finished(const T *value);
Leider funktionieren virtuelle Signale ebenfalls nicht, folgende Deklaration ist also auch falsch:

Code: Alles auswählen

signals: 
    virtual void finished(const BaseClass *value);
Ich habe nun folgendes Problem. Ich habe eine Basisklasse Adapter und eine Basisklasse Job:

Code: Alles auswählen

class Adapter : public QObject
{
    //...
};

Code: Alles auswählen

class Job : public QObject 
{
    //...
    signals:
        void finished(Job *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:

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;
};
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:

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);
};
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
Antworten