简体   繁体   中英

casting from interface to QObject

I have an interface class in a header file like this.

class Interface
{
...
}
#define InterfaceIID "Interface"
Q_DECLARE_INTERFACE(Interface, InterfaceIID)

which is expected to be implemented like this

class Implementation : public QWidget, public Interface
{
    Q_OBJECT
    Q_INTERFACES(Interface)
    ...
}

I have pointers to objects implementing my interface being passed around in my application. Now i know know that every Interface object is also a QWidget because that is the only supported use case.

My question is now, when i am in need of a QWidget object, how do i cast my Interface object to a QWidget?

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

Is using dynamic_cast() the only way? I can cast from QWidget to Interface using qobject_cast() but the reverse does not work.

I understand that dynamic_cast() is unsafe across shared libraries and hence i'm trying to avoid it.

What is the right approach?

The second one is right. qObjectCast is ment to cast a QObject to "anything", not the other way around. Thats what dynamic casts are for:

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

Note: the qobject_cast above could easily be replaced with a dynamic_cast . However, if possible, always use qobject_cast . Reason (from the 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.

It uses Qts metasystem (QMetaObject) to perform the cast. And, in addition to that, it seems to be way faster then dynamic_cast .

The reason you can't use the qobject_cast to cast the interface to a QWidget is that the interface itself does not inherit QObject (and does not have the Q_OBJECT macro). Thus, it has no metaobject and qobject_cast cannot be used.

EDIT:
One way to avoid dynamic casting is to always keep the plugin as a QObject . If you need it as widget, cast it with qobject_cast . Same goes for your Interface . As long as you store/pass around the instance as QObject , you will never have to dynamic_cast.

Note: If you need to know the kind of plugin, create a small wrapper classes for each of the interfaces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM