使用Qt信号与多重继承的槽函数

9

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

class MyClass : public QGraphicsTextItem, public MyInterface

我需要能够在 MyInterface* 上使用 connectdisconnect。但似乎 connectdisconnect 仅适用于 QObject* 实例。由于 Qt 不支持从 QObject 派生类进行多重继承,我无法从 QObject 派生 MyInterface。(对于接口而言那也没有太多意义。)
有一个在线讨论,但在常见情况下(通过其接口访问对象),我认为所提议的解决方案相当无用,因为你不能连接来自MyInterface*的信号和槽,而必须将其转换为派生类型。由于 MyClass 是许多 MyInterface-派生类之一,这将导致“代码臭味”——if-this-cast-to-this-else-if-that-cast-to-that语句,并破坏了接口的目的。
有没有好的解决此限制的方法?
更新:我注意到如果我将 MyInterface* 动态转换为 QObject*(因为我“知道”所有的 MyInterface-派生类最终都继承自 QObject),它似乎可以工作。也就是说:
MyInterface *my_interface_instance = GetInstance();
connect(dynamic_cast<QObject*>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));

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


你是在哪里声明MyInterfaceSignal的?声明方式是怎样的? - Frank Osterfeld
MyInterfaceSignalMyInterface 中被声明为非信号的受保护纯虚方法,然后在派生类中被声明为信号。因此,编译器确保派生类具有该方法,但实现者需要将其标记为信号。这很奇怪,因为我并不是真的从 MyInterface.MyInterfaceSignal 调用虚调用表,而是依赖于 SIGNAL 宏最终解析为 char* 方法名的事实。 - Dave Mateer
2个回答

12
您自己找到了答案:dynamic_cast的使用方式与您预期的相同,这不是未定义行为。如果您获得的MyInterface实例不是QObject,则转换将返回null,您可以防范此类情况(尽管这不会发生,因为您说接口的所有实例也都是QObjects)。但请记住,您需要开启RTTI才能使其正常工作。
我还想提出一些建议:
  • 使用 Q_INTERFACES 功能(它不仅适用于插件)。然后您将以QObject为术语,并在真正需要时使用qobject_cast查询MyInterface 。我不知道您的问题的详细信息,但既然您知道所有MyInterface实例也都是QObjects,则这似乎是最明智的方法。
  • 向MyInterface添加 QObject * asQObject()抽象方法,并在所有子类中将其实现为{return this; }。
  • 拥有QGraphicsTextItem(组合)而不是成为一个(继承)。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接