2010-12-09 10 views
28

¿Es posible tener una clase de plantilla, que hereda de QObject (y tiene macro Q_OBJECT en su declaración)?QT: clase Q_OBJECT templada

Me gustaría crear algo así como un adaptador para ranuras, lo que haría algo, pero la ranura puede tomar un número arbitrario de argumentos (el número de argumentos depende del argumento de la plantilla).

Solo traté de hacerlo, y obtuve errores de enlazador. Supongo que gmake o moc no recibirán una llamada en esta clase de plantilla. ¿Hay alguna forma de hacer esto? ¿Tal vez al crear instancias explícitas de plantillas?

+0

¿Has observado el modelo de inclusión? :) http://linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_134.html –

+0

@Armen Sí, no pensé en eso. Pensé que el preprocesador de qt lo mataría. –

Respuesta

1

Probé plantillas instanciar explícitamente, y obtuve esto:

core_qta_qt_publisheradapter.hpp: 96: error: clases de plantilla no soportados por Q_OBJECT

supongo que eso responde a mi pregunta.

EDITAR

En realidad, si pongo toda definición de la clase de plantilla en la cabecera, a continuación, el preprocesador qt no lo procesa, cuando me siento errores de enlace. Por lo tanto, debe ser posible hacerlo, si agrego métodos faltantes.

editar # 2

This library hicieron exactamente lo que quería - utilizar un mecanismo de señal personalizada/ranura, donde la ranura de la firma no se ha definido.

9

Teniendo en cuenta algunas restricciones: puede hacerlo. Primero, familiarícese (si no es así) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html. - ayudará a imponerlo. Y acerca de las restricciones: se puede tener una clase de plantilla es decir plantilla de clase QObject derivado de QObject, pero:

  1. no dicen la moc para compilarlo.
  2. Q_OBJECT es sólo una macro y hay que sustituirlo por el contenido real que es interfaz virtual y algo más :)
  3. Implementar la activación QMetaObject (por encima de interfaz virtual mencionado y ser cuidado con los datos de información objeto, que se también vienen de Q_OBJECT) y algunas funciones más y tendrá plantilla QObject (incluso con ranuras plantilla)
  4. Pero a medida que me las arreglé para coger el único inconveniente - no es posible simplemente uso esta clase como una base para otra clase.
  5. Existen otros inconvenientes, pero creo que la investigación de detalles se los mostrará.

Espero que esto sea útil.

23

No es posible mezclar plantilla y Q_OBJECT pero si usted tiene un subconjunto de tipos que puede enumerar las ranuras y señales como esta:

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

Separación simple de nociones ...! – g24l

+1

Buen trabajo. Además, si las definiciones de señal necesitan acceder al parámetro de la plantilla, pueden declararse simplemente como abstract virtual en el equivalente de SignalsSlots y definirse en la plantilla de la clase. –

+0

¿Puedes explicar eso? La clase 'SignalsSlots' no es una clase de plantilla, así que ¿cómo puedo usar un parámetro de Plantilla en la firma de la señal? Por ejemplo, si quisiera hacer algo como esto: 'void someSignal (T value)'. – user1488118

1

todavía no es posible plantillas y Q_OBJECT mezcla, pero dependiendo en su caso de uso, puede usar la nueva sintaxis 'connect'. Esto permite al menos el uso de ranuras de plantilla.

enfoque clásico no trabaja:

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. */} 
}; 

el uso deseado, pero no compilables:

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).

solución usando la nueva 'connect'-sintaxis:

// 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. */} 
}; 

Ahora podemos instanciar los objetos 'MySlotClass' que desee y conectarlos a los emisores de señal apropiados.

MySignalClass a; 
    MySlotClass<int> b; 

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

Conclusión: Uso de plantilla ranuras es posible. La emisión de señales de plantilla no funciona, ya que se producirá un error de compilación debido a que falta Q_OBJECT.

Cuestiones relacionadas