使用具有多重继承的Qt信号和插槽

时间:2010-07-15 20:25:08

标签: c++ qt multiple-inheritance qt-signals

我有一个类(MyClass)从Qt内置对象(QGraphicsTextItem)继承了它的大部分功能。 QGraphicsTextItem间接从QObject继承。 MyClass还实现了一个界面MyInterface

class MyClass : public QGraphicsTextItem, public MyInterface

我需要能够在connect上使用disconnectMyInterface*。但似乎connectdisconnect仅适用于QObject*个实例。由于Qt不支持来自QObject派生类的多重继承,因此我无法从MyInterface派生QObject。 (无论如何,这对于界面也没有多大意义。)

有一个discussion of the problem online,但IMO提出的解决方案在常见情况下(通过其接口访问对象)相当无用,因为您无法连接来自MyInterface*的信号和插槽但必须强制转换它到派生类型。由于MyClass是许多MyInterface派生类中的一个,因此如果 - 这个 - 转换为此其他 - 如果 - 那个 - 转换为该语句,则需要“代码异味”打败了界面的目的。

这个限制是否有一个很好的解决方案?

更新:我注意到,如果我dynamic_cast MyInterface*QObject*(因为我知道全部MyInterface } -derived类最终也从QObject继承,它似乎有用。那就是:

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

但是这个真的似乎我要求未定义的行为......

2 个答案:

答案 0 :(得分:12)

您自己找到了答案:dynamic_cast正如您所期望的那样工作。它不是未定义的行为。如果您获得的MyInterface实例不是QObject,则转换将返回null并且您可以保护自己(这不会发生,因为您说接口的所有实例也是QObjects)。但请记住,您需要启用RTTI才能使其正常工作。

我还会提出一些其他建议:

  • 使用 Q_INTERFACES 功能(它不仅适用于插件)。然后,当真正需要时,您将使用QObject并使用qobject_cast查询MyInterface。我不太详细地了解你的问题,但既然你知道所有的MyInterface实例都是QObjects,这似乎是最明智的方法。

  • 向MyInterface添加QObject* asQObject()抽象方法,并在所有子类中将其实现为{ return this; }

  • 拥有 QGraphicsTextItem(组合)而不是 一个(继承)。

答案 1 :(得分:7)

您可以声明在其构造函数中包含QObject的MyInterface:

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

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

然后在MyClass构造函数中:

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

你可以连接信号:

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