从接口转换为 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的主要内容,如果未能解决你的问题,请参考以下文章