9

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

class MyClass : public QGraphicsTextItem, public MyInterface

我需要能够使用connectdisconnect打开MyInterface*. 但它似乎connectdisconnect适用于QObject*实例。由于 Qt 不支持从 QObject 派生类进行多重继承,因此我无法MyInterfaceQObject. (无论如何,这对接口也没有多大意义。)

网上对此问题进行了讨论,但 IMO 提出的解决方案在常见情况下(通过其接口访问对象)相当无用,因为您无法连接信号和插槽,MyInterface*但必须将其转换为派生类型。由于MyClass是许多 -MyInterface派生类之一,这将需要“代码异味” if-this-cast-to-this-else-if-that-c​​ast-to-that 语句并破坏接口的目的。

这个限制有没有好的解决方案?

更新:我注意到如果我dynamic_casta MyInterface*to QObject*(因为我知道所有MyInterface派生类最终也继承自QObject,它似乎工作。那是:

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

但这真的好像我在要求未定义的行为......

4

2 回答 2

12

您自己找到了答案:dynamic_cast 按您的预期工作。这不是未定义的行为。如果您获得的 MyInterface 实例不是 QObject,则强制转换将返回 null 并且您可以防范这种情况(这不会发生,因为您说接口的所有实例也是 QObjects)。但是请记住,您需要打开 RTTI 才能使其工作。

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

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

  • QObject* asQObject()向 MyInterface添加一个抽象方法,并像{ return this; }在所有子类中一样实现它。

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

于 2010-07-17T23:00:53.520 回答
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()));
于 2010-07-15T22:09:17.900 回答