El uso de Qt señales y slots con la herencia múltiple
-
16-09-2020 - |
Pregunta
Tengo una clase (MyClass
) que hereda la mayor parte de su funcionalidad de un Qt objeto incorporado (QGraphicsTextItem
). QGraphicsTextItem
hereda indirectamente de QObject
. MyClass
también implementa una interfaz, MyInterface
.
class MyClass : public QGraphicsTextItem, public MyInterface
Necesito ser capaz de utilizar connect
y disconnect
en MyInterface*
.Pero parece que connect
y disconnect
sólo el trabajo en QObject*
las instancias.Desde Qt no soporta la herencia múltiple de QObject derivados de clases, que no puedo derivar MyInterface
de QObject
.(Ni que tenga mucho sentido para una interfaz de todos modos.)
Hay un la discusión del problema en línea, pero la OMI, la solución propuesta es bastante inútil en el común de los casos (en el acceso a un objeto a través de su interfaz), debido a que no se puede conectar las señales y slots de MyInterface*
pero debe echarlo a los derivados de tipo.Desde MyClass
es uno de los muchos MyInterface
-las clases derivadas, sería necesario "código huele mal" si-esta-elenco-para-este-los demás-si-que-de fundición--de que las declaraciones y derrota el propósito de la interfaz.
Hay una buena solución a esta limitación?
ACTUALIZACIÓN: Me di cuenta de que si me dynamic_cast
un MyInterface*
a QObject*
(porque yo saber todos MyInterface
-las clases derivadas heredan también, finalmente, de QObject
, parece que funciona.Que 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....
Solución
Has encontrado la respuesta a sí mismo:el dynamic_cast funciona como es de esperar.No es un comportamiento indefinido.Si la instancia de Miinterfaz tienes no es un QObject, el elenco devolverá null y usted puede protegerse contra el que (que no sucederá, ya que dijo que todas las instancias de la interfaz son también QObjects).Sin embargo, recuerde que usted necesita RTTI activado para que funcione.
También me gustaría ofrecer algunas otras sugerencias:
El uso de la Q_INTERFACES característica (no sólo para los plugins).Entonces quieres trabajar en términos de QObject y consulta para Miinterfaz utilizando qobject_cast cuando es realmente necesario.No sé con detalle tu problema, pero ya que usted sabe que todos los Miinterfaz casos son también QObjects, este parece ser el método más sensato.
Añadir un
QObject* asQObject()
método abstracto para Miinterfaz y su aplicación como{ return this; }
en todas las subclases.Tener un QGraphicsTextItem (composición) en lugar de siendo uno (herencia).
Otros consejos
Usted puede declarar Miinterfaz que toma 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)
{
...
}
A continuación, 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()));