2010-12-09 2 views
28

Ist es möglich, eine Vorlage Klasse, die von QObject erben (und hat Q_OBJECT Makro in seiner Deklaration)?QT: Templated Q_OBJECT Klasse

Ich möchte etwas wie Adapter für Slots erstellen, die etwas tun würden, aber der Steckplatz kann eine beliebige Anzahl von Argumenten (Anzahl der Argumente hängt von der Vorlage Argument).

Ich habe es gerade versucht, und bekam Linker Fehler. Ich denke, Gmake oder Moc wird nicht in dieser Template-Klasse aufgerufen. Gibt es eine Möglichkeit, dies zu tun? Vielleicht durch explizite Instanziierung von Vorlagen?

+0

Haben Sie das Inklusionsmodell beobachtet? :) http://linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_134.html –

+0

@Armen Ja, ich habe nicht darüber nachgedacht. Ich dachte, qt preprocessor würde es kauen. –

Antwort

1

Ich habe versucht, explizit instanziieren Vorlagen und bekam dies:

core_qta_qt_publisheradapter.hpp: 96: Fehler: Template-Klassen unterstützt nicht von Q_OBJECT

Ich denke, dass meine Frage beantwortet.

EDIT

Eigentlich, wenn ich ganze Vorlage Klassendefinition im Header platzieren, dann die qt Präprozessor nicht verarbeitet, und dann bekomme ich Linkerfehler. Daher muss es möglich sein, wenn ich fehlende Methoden hinzufüge.

EDIT # 2

This library tat genau das, was ich wollte - ein eigenes Signal/Slot-Mechanismus verwenden, bei dem der Schlitz Unterschrift nicht-definiert hat.

9

Unter Berücksichtigung einiger Einschränkungen: Sie können. Zuerst kam bitte bekannt (wenn schon nicht) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html. - Es wird helfen, es einzubauen. Und über Einschränkungen: Sie können eine Vorlage QObject Klasse heißt Template-Klasse von QObject abgeleitet haben, aber:

  1. nicht moc es zu kompilieren sagen Sie.
  2. Q_OBJECT ist nur ein Makro und Sie haben es durch es wirklich Inhalt zu ersetzen, die virtuelle Schnittstelle und etwas anderes ist :)
  3. Implementieren QMetaObject Aktivierung (oben erwähnte virtuelle Schnittstelle und Vorsicht sein mit Datenobjekt info, das ist auch kommen aus Q_OBJECT) und einige andere Funktionen, und Sie werden das eine zurückziehen
  4. Aber wie ich es geschafft, zu fangen Vorlage QObject (auch mit Template Slots) - es einfach Einsatz nicht möglich ist, diese Klasse als eine Basis für eine andere Klasse.
  5. Es gibt einige andere Nachteile - aber ich denke, das Detail Untersuchung wird Ihnen zeigen.

Hoffe, dies wird hilfreich sein.

23

Es ist nicht möglich, Vorlage und Q_OBJECT zu mischen, aber wenn Sie eine Teilmenge der Typen haben können Sie die Slots und Signale wie diese Liste:

class SignalsSlots : public QObject 
    { 
     Q_OBJECT 

    public: 
     explicit SignalsSlots(QObject *parent = 0) : 
      QObject(parent) {} 

    public slots: 
     virtual void writeAsync(int value) {} 
     virtual void writeAsync(float value) {} 
     virtual void writeAsync(double value) {} 
     virtual void writeAsync(bool state) {} 
     virtual void writeAsync(svga::SSlideSwitch::SwitchState state) {} 

    signals: 
     void readAsynkPolledChanged(int value); 
     void readAsynkPolledChanged(float value); 
     void readAsynkPolledChanged(double value); 
     void readAsynkPolledChanged(bool state); 
     void readAsynkPolledChanged(svga::SSlideSwitch::SwitchState state); 
    }; 
... 
template <class T> 
class Abstraction : public SignalsSlots 
{... 
+1

Einfache Trennung der Begriffe ...! – g24l

+1

Gute Work-around. Wenn die Signaldefinitionen auf den Vorlagenparameter zugreifen müssen, können sie darüber hinaus einfach als virtuelles Abstrakt in der SignalSlots-Entsprechung deklariert und in der Klassenvorlage definiert werden. –

+0

Können Sie das erklären? Die Klasse 'SignalsSlots' ist keine Template-Klasse. Wie kann ich einen Template-Parameter in der Signatur des Signals verwenden? Zum Beispiel, wenn ich so etwas machen wollte: 'void someSignal (T-Wert)'. – user1488118

1

Es ist noch nicht möglich, Vorlagen und Q_OBJECT zu mischen, aber je In Ihrem Anwendungsfall können Sie die neue 'connect'-Syntax verwenden. Dies ermöglicht zumindest die Verwendung von Vorlagen-Slots.

Klassische Nicht-Arbeitsansatz:

class MySignalClass : public QObject { 
    Q_OBJECT 
public: 

signals: 
    void signal_valueChanged(int newValue); 
};  


template<class T> 
class MySlotClass : public QObject { 
    Q_OBJECT 
public slots: 
    void slot_setValue(const T& newValue){ /* Do sth. */} 
}; 

Wunsch Nutzung aber nicht übersetzbar:

MySignalClass a; 
MySlotClass<int> b; 

QObject::connect(&a, SIGNAL(signal_valueChanged(int)), 
       &b, SLOT(slot_setValue(int))); 

Error: Template classes not supported by Q_OBJECT (For MySlotClass).

Lösung mit neuen die ‚Connect'-Syntax:

// Nothing changed here 
class MySignalClass : public QObject { 
    Q_OBJECT 
public: 

signals: 
    void signal_valueChanged(int newValue); 
}; 


// Removed Q_OBJECT and slots-keyword 
template<class T> 
class MySlotClass : public QObject { // Inheritance is still required 
public: 
    void slot_setValue(const T& newValue){ /* Do sth. */} 
}; 

Nun können wir gewünschte 'MySlotClass'-Objekte instanziieren und mit entsprechenden Signalemittern verbinden.

MySignalClass a; 
    MySlotClass<int> b; 

    connect(&a, &MySignalClass::signal_valueChanged, 
      &b, &MySlotClass<int>::slot_setValue); 

Fazit: Template-Slots ist möglich. Das Ausgeben von Vorlagensignalen funktioniert nicht, da aufgrund von fehlendem Q_OBJECT ein Compilerfehler auftreten wird.