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

Dav*_*eer 9 c++ qt multiple-inheritance qt-signals

我有一个class(MyClass)从Qt内置对象(QGraphicsTextItem)继承其大部分功能.QGraphicsTextItem从中间接继承QObject.MyClass还实现了一个接口MyInterface.

class MyClass : public QGraphicsTextItem, public MyInterface
Run Code Online (Sandbox Code Playgroud)

我需要能够使用connectdisconnect开启MyInterface*.但现在看来,connectdisconnect只在工作QObject*实例.由于Qt不支持从QObject的派生类多继承,我不能得到MyInterfaceQObject.(无论如何,这对于界面也没有多大意义.)

有一个问题的讨论在网上,但IMO所提出的解决方案是在通常情况下(访问通过其接口的对象)相当无用的,因为你无法连接的信号和槽MyInterface*,但必须将它转换为派生类型.由于MyClass是许多MyInterface衍生类中的一个,这将需要"代码 - 臭"如果 - 这个 - 演绎 - 否则 - 如果 - 那个 - 演绎到那个语句并且破坏了接口的目的.

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

更新:我注意到,如果我dynamic_castMyInterface*QObject*(因为我知道所有MyInterface的派生类也最终从继承QObject,它似乎工作即:

MyInterface *my_interface_instance = GetInstance();
connect(dynamic_cast<QObject*>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));
Run Code Online (Sandbox Code Playgroud)

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

and*_*ref 12

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

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

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

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

  • 具有一个QGraphicsTextItem(组合物),而不是作为一个(继承).


Ste*_*Chu 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)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后在MyClass构造函数中:

MyClass::MyClass() :
MyInterface(this)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

你可以连接信号:

MyInterface *my_interface_instance = GetInstance();
connect(my_interface_instance->object(), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));
Run Code Online (Sandbox Code Playgroud)