从接口转换为QObject

3
我在头文件中有一个接口类,代码如下。
class Interface
{
...
}
#define InterfaceIID "Interface"
Q_DECLARE_INTERFACE(Interface, InterfaceIID)

预计将实施如下所示。
class Implementation : public QWidget, public Interface
{
    Q_OBJECT
    Q_INTERFACES(Interface)
    ...
}

我在我的应用程序中传递实现我的接口的对象指针。现在我知道每个接口对象也是一个QWidget,因为这是唯一支持的用例。

我的问题是,当我需要一个QWidget对象时,如何将我的接口对象强制转换为QWidget?

qobject_cast<QWidget*>(interface) //does not compile
dynamic_cast<QWidget*>(interface) //works but is it the right way?

使用dynamic_cast()是唯一的方法吗?我可以使用qobject_cast()将QWidget强制转换为Interface,但是反向操作不起作用。

我知道dynamic_cast()在共享库中不安全,因此我试图避免使用它。

正确的方法是什么?


首先将“Interface”转换为“Implementation”,然后将“Implementation”转换为“QWidget”。我怀疑“Interface”无法转换为“QWidget”,因为它们似乎不属于同一继承链。 - rozina
@rozina QWidget 可能是接口的基本实现(从给定的代码无法知道),因此从 Interface* 到 QWidget* 的转换可能有效。使用 dynamic_cast 可以安全地得到答案。 - Neil
@rozina 很抱歉,我不能这样做。在发生强制类型转换的地方,代码并不知道具体的实现细节。它只知道接口,并且假设实现也应该从QWidget继承,就像文档中所描述的那样。 - Kishore Jonnalagadda
1个回答

4
第二个是正确的。qObjectCast 用于将 QObject 强制转换为“任何内容”,而不是相反。这就是动态转换的作用:
QObject *intfObject = pluginLoader.instance();
Interface *intf = qobject_cast<Interface *>(intfObject);//only works if the object has Q_INTERFACES(Interface)
QWidget *intfWidget = dynamic_cast<QWidget*>(intf);

注意:上面的qobject_cast可以很容易地替换为dynamic_cast。 但是,如果可能,始终使用qobject_cast。 原因(来自文档):

qobject_cast()函数类似于标准的C ++ dynamic_cast(),具有不需要RTTI支持和跨动态库边界工作的优点。

它使用Qt元系统(QMetaObject)执行转换。此外,它似乎比 dynamic_cast 要快得多。
您无法使用qobject_cast将接口强制转换为 QWidget 的原因是接口本身未继承QObject(并且没有 Q_OBJECT 宏)。 因此,它没有元对象,不能使用 qobject_cast
编辑:
避免使用动态类型转换的一种方法是始终将插件保留为 QObject 。 如果需要将其用作小部件,则使用 qobject_cast 进行转换。 您的 Interface 也是如此。 只要将实例存储/传递为 QObject ,则永远不需要执行dynamic_cast。
注意:如果需要知道插件的类型,请为每个接口创建小包装类。

使用dynamic_cast()是安全的吗?接口和执行转换的代码位于一个库中(在我的情况下,来自主应用程序),而实现来自另一个库(插件)。 - Kishore Jonnalagadda
据我所知,是的。因为Qt以“正确的方式”加载插件。至少对我来说,动态转换一直都有效。但如果您对此解决方案感到不舒服,请查看我的编辑过的帖子。 - Felix

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