Using Qt signals and slots with multiple inheritance
-
I need to use multiple inheritance because I need to (1) implement an "is-a" relationship from QGraphicsItem, and (2) implement an application-specific interface (MyInterface):
@class MyClass : public QGraphicsTextItem, public MyInterface@
I would like to connect to signals from pointers to the interface, i.e.:
@MyInterface *my_interface_instance = GetInstance();
connect(my_interface_instance, SIGNAL(MyInterfaceSignal()), this, SLOT(SomeSlot()));@Problem: To expose signals in MyInterface, it needs to derive from QObject. But then I have multiple-inheritance from QObject, which is not allowed. The solutions on "this article":http://doc.trolltech.com/qq/qq15-academic.html are IMO fairly useless in the common case (accessing an object through its interface), because you cannot connect the signals and slots from MyInterface* but must cast it to the derived-type. Since MyClass is one of many MyInterface-derived classes, this would necessitate "code-smelly" if-this-cast-to-this-else-if-that-cast-to-that statements and defeats the purpose of the interface.
The solution below seems to work, but I was hoping a Troll could let me know if this is supported or is going to cause undefined behavior. If I dynamic_cast a MyInterface* to QObject* (because I know all MyInterface-derived classes also inherit eventually from QObject), it seems to work:
@class MyInterface {
protected:
virtual void MyInterfaceSignal() = 0;
};class MyClass : public QGraphicsTextItem, public MyInterface {
Q_OBJECT
signals:
void MyInterfaceSignal();
};
@Usage:
@MyInterface my_interface_instance = GetInstance();
connect(dynamic_cast<QObject>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(SomeSlot()));@Is this a bad idea?
-
I'm far from being a Troll but we used massively the same idea to work around QObjects not being able to be put into templates.
We had no issue with Qt 4.5, 4.6 and 4.7beta so far
-
We had a similar discussion recently, and one of the options would be that in your interface's constructor, you'd take a QObject* of the actual instance.
Your class's constructor would look like:
@
MyClass::MyClass()
: MyInterface(this) {}
@That way, you could use the QObject pointer in your interface to connect signals and slots.
Also, you could take a look at "QDBusAbstractAdaptor":http://doc.qt.nokia.com/4.7-snapshot/qdbusabstractadaptor.html that basically "attaches" an interface to any given QObject.
-
I guess this is an old post but just wanted to add that harryF's solution (i.e. pass in a pointer to the concrete class to the interface and do all the connections off that pointer) is pretty much exactly the same solution I implemented on a project I worked on recently.