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

发布于 2024-09-10 06:16:18 字数 1356 浏览 11 评论 0原文

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

class MyClass : public QGraphicsTextItem, public MyInterface

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

有一个 在线讨论该问题,但 IMO 提出的解决方案在常见情况下(通过其接口访问对象)相当无用,因为您无法从 MyInterface* 连接信号和槽,而必须将其强制转换为派生类型。由于 MyClass 是许多 MyInterface 派生类之一,因此需要“代码臭” if-this-cast-to-this-else-if-that-c​​ast -to that 陈述并违背了界面的目的。

有没有好的办法解决这个限制呢?

更新:我注意到,如果我dynamic_castMyInterface*转换为QObject*(因为我知道< /em> 所有 MyInterface 派生类最终也继承自 QObject,这似乎有效:

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

但这确实看起来像我。要求未定义的行为......

I have a class (MyClass) that inherits most of its functionality from a Qt built-in object (QGraphicsTextItem). QGraphicsTextItem inherits indirectly from QObject. MyClass also implements an interface, MyInterface.

class MyClass : public QGraphicsTextItem, public MyInterface

I need to be able to use connect and disconnect on MyInterface*. But it appears that connect and disconnect only work on QObject* instances. Since Qt does not support multiple inheritance from QObject-derived classes, I cannot derive MyInterface from QObject. (Nor would that make much sense for an interface anyway.)

There is a discussion of the problem online, but IMO the proposed solution is 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.

Is there a good solution to this limitation?

UPDATE: I noticed that if I dynamic_cast a MyInterface* to QObject* (because I know all MyInterface-derived classes also inherit eventually from QObject, it seems to work. That is:

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

But this really seems like I am asking for undefined behavior....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水波映月 2024-09-17 06:16:18

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

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

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

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

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

You found the answer yourself: the dynamic_cast works as you would expect. It is not undefined behavior. If the instance of MyInterface you got is not a QObject, the cast will return null and you can guard yourself against that (which won't happen, since you said all instances of the interface are also QObjects). Remember, however, that you need RTTI turned on for it to work.

I would also offer a few other suggestions:

  • Use the Q_INTERFACES feature (it's not only for plug-ins). Then you'd work in terms of QObject and query for MyInterface using qobject_cast when it is really needed. I don't know your problem in detail, but since you know that all MyInterface instances are also QObjects, this seems to be the most sensible approach.

  • Add a QObject* asQObject() abstract method to MyInterface and implement it as { return this; } in all subclasses.

  • Having a QGraphicsTextItem (composition) instead of being one (inheritance).

停顿的约定 2024-09-17 06:16:18

您可以声明 MyInterface 在其构造函数中采用 QObject:

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()));

You can declare MyInterface that takes a QObject in its constructor:

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

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

Then in MyClass constructor:

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

And you can connect the signal:

MyInterface *my_interface_instance = GetInstance();
connect(my_interface_instance->object(), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文