2010-07-15 18 views
9

Tengo una clase (MyClass) que hereda la mayor parte de su funcionalidad de un objeto incorporado Qt (QGraphicsTextItem). QGraphicsTextItem hereda indirectamente de QObject. MyClass también implementa una interfaz, MyInterface.Uso de señales Qt y ranuras con herencia múltiple

class MyClass : public QGraphicsTextItem, public MyInterface 

tengo que ser capaz de utilizar connect y disconnect en MyInterface*. Pero parece que connect y disconnect solo funcionan en instancias QObject*. Como Qt no admite herencia múltiple de clases derivadas de QObject, no puedo derivar MyInterface de QObject. (Tampoco tendría mucho sentido para una interfaz de todos modos)

Hay discussion of the problem online, pero la solución propuesta es bastante inútil en el caso común (acceder a un objeto a través de su interfaz), porque no se puede conectar las señales y ranuras desde MyInterface* pero deben convertirlo al tipo derivado. Dado que MyClass es una de las muchas clases derivadas de MyInterface, esto requeriría sentencias "si huele mal" si-esto-arrojar-a-otra-cosa-si-que-arrojó-a-esa y derrota el propósito de la interfaz.

¿Existe una buena solución a esta limitación?

ACTUALIZACIÓN: me di cuenta de que si dynamic_cast un MyInterface*-QObject* (porque yo sé MyInterface todas las clases -derivado también hereda el tiempo de QObject, parece que funciona Esto es:.

MyInterface *my_interface_instance = GetInstance(); 
connect(dynamic_cast<QObject*>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot())); 

Pero este realmente parece que estoy pidiendo un comportamiento indefinido ....

+0

¿Cómo y cuándo declaras MyInterfaceSignal? –

+0

'MyInterfaceSignal' se declara como un método virtual puro protegido * sin señal * en' MyInterface', y luego como * signal * en clases derivadas. Por lo tanto, el compilador asegura que las clases derivadas tienen el método, pero le corresponde al implementador marcarlo como una señal. Es cursi, porque no estoy * realmente * llamando a la tabla de llamadas virtuales desde 'MyInterface.MyInterfaceSignal', sino confiando en el hecho de que la macro SIGNAL es, al final del día, simplemente resolviendo un' char * 'nombre del método. –

Respuesta

12

Encontraste la respuesta por ti mismo: el moldeado dinámico funciona como usted esperaría No es un comportamiento indefinido. Si la instancia de MyInterface que obtuvo no es un QObject, el yeso devolverá nulo y podrá protegerse de eso (lo que no sucederá, ya que dijo que todas las instancias de la interfaz también son QObjects). Recuerde, sin embargo, que necesita RTTI encendido para que funcione.

También ofrecería algunas otras sugerencias:

  • Uso del Q_INTERFACES función (que no es sólo para los plug-ins). Entonces trabajarías en términos de QObject y consultas para MyInterface usando qobject_cast cuando realmente se necesita. No conozco su problema en detalle, pero dado que usted sabe que todas las instancias de MyInterface también son QObjects, este parece ser el enfoque más sensato.

  • Agregue un método abstracto QObject* asQObject() a MyInterface e impleméntelo como { return this; } en todas las subclases.

  • Tener un QGraphicsTextItem (composición) en lugar de ser uno (herencia).

6

Puedes declarar MyInterface that ta kes un QObject en su constructor:

class MyInterface { 
public: 
       MyInterface(QObject * object); 
    QObject * object() { return m_object; } 
    ... 
private: 
    QObject * m_object; 
}; 

MyInterface::MyInterface(QObject * object) : 
    m_object(object) 
{ 
    ... 
} 

Luego, en MiClase constructor:

MyClass::MyClass() : 
MyInterface(this) 
{ 
    ... 
} 

Y se puede conectar la señal:

MyInterface *my_interface_instance = GetInstance(); 
connect(my_interface_instance->object(), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot())); 
Cuestiones relacionadas