从接口转换为 QObject

Posted

技术标签:

【中文标题】从接口转换为 QObject【英文标题】:casting from interface to QObject 【发布时间】:2016-06-27 12:00:02 【问题描述】:

我在这样的头文件中有一个接口类。

class Interface

...

#define InterfaceIID "Interface"
Q_DECLARE_INTERFACE(Interface, InterfaceIID)

预计会这样实现

class Implementation : public QWidget, public Interface

    Q_OBJECT
    Q_INTERFACES(Interface)
    ...

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

我现在的问题是,当我需要 QWidget 对象时,如何将我的 Interface 对象转换为 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 转换为Impelemntation,然后将Implementation 转换为QWidget。我怀疑Interface 是否可以转换为QWidget,因为它们似乎不是同一继承链的一部分。 @rozina QWidget 可能是 Interface 的基本实现(无法从给出的代码中得知),因此从 Interface* 到 QWidget* 的转换可以工作。 dynamic_cast 会安全地给出答案。 @rozina 不幸的是,我不能这样做。发生这种转换的地方,代码不知道实现。它只知道接口并假设实现也从 QWidget 继承,如文档所述。 【参考方案1】:

第二个是对的。 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。原因(来自documentation):

qobject_cast() 函数的行为类似于标准 C++ dynamic_cast(),其优点是它不需要 RTTI 支持并且可以跨动态库边界工作。

它使用 Qts 元系统 (QMetaObject) 来执行转换。而且,除此之外,它似乎比dynamic_cast 更快。

您不能使用 qobject_cast 将接口转换为QWidget 的原因是接口本身不继承 QObject(并且没有Q_OBJECT 宏)。因此,它没有元对象,不能使用qobject_cast

编辑: 避免动态转换的一种方法是始终将插件保留为QObject。如果您需要它作为小部件,请使用qobject_cast 进行投射。您的Interface 也是如此。只要您将实例存储/传递为QObject,您就不必进行动态转换。

注意:如果您需要了解插件的种类,请为每个接口创建一个小型包装类。

【讨论】:

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

以上是关于从接口转换为 QObject的主要内容,如果未能解决你的问题,请参考以下文章

如何从 c++ 接口 cv::Mat 转换为 c IplImage?

从接口转换到类,糟糕的设计还是小违规?

将 JSON 接口转换为数组

将对象转换为 TypeScript 中的接口

将串行接口数据转换为整数

FT232RL为接口转换芯片,可以实现USB到串行UART接口的转换