从接口转换为 QObject

casting from interface to QObject

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

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 转换到接口,但反过来不起作用。

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

什么是正确的做法?

第二个是对的。 qObjectCast 是为了将 QObject 转换为 "anything",而不是相反。这就是动态转换的用途:

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):

The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.

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

快得多

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

编辑:
避免动态转换的一种方法是始终将插件保持为 QObject。如果你需要它作为小部件,用 qobject_cast 投射它。您的 Interface 也是如此。只要您 store/pass 围绕实例 QObject,您将永远不必 dynamic_cast.

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