2016-06-27 15 views
0

Ich habe eine Interface-Klasse in einer Header-Datei wie folgt.Umwandlung von Interface zu QObject

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

, die wie dieser

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

ich Zeiger auf Objekte haben meine Schnittstelle in meiner Anwendung übergeben um wird die Umsetzung durchgeführt wird zu erwarten. Jetzt weiß ich, dass jedes Interface-Objekt auch ein QWidget ist, da dies der einzige unterstützte Anwendungsfall ist.

Meine Frage ist jetzt, wenn ich ein QWidget-Objekt benötige, wie gieße ich mein Interface-Objekt an ein QWidget?

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

Verwenden Sie dynamic_cast() die einzige Möglichkeit? Ich kann mit qobject_cast() von QWidget auf Interface umwandeln, aber das Gegenteil funktioniert nicht.

Ich verstehe, dass dynamic_cast() über gemeinsame Bibliotheken unsicher ist und daher versuche ich es zu vermeiden.

Was ist der richtige Ansatz?

+0

Zuerst die "Schnittstelle" zu "Impelentation" umsetzen und dann "Implementierung" in "QWidget" umwandeln. Ich bezweifle, dass "Interface" in ein "QWidget" umgewandelt werden kann, da sie nicht Teil derselben Vererbungskette sind. – rozina

+0

@rozina QWidget könnte möglicherweise eine Basisimplementierung von Interface sein (keine Möglichkeit, aus dem angegebenen Code zu unterscheiden), so dass ein Cast von Interface * nach QWidget * funktionieren könnte. dynamic_cast gibt die Antwort sicher. – Neil

+0

@rozina Leider kann ich das nicht tun.Wo diese Besetzung stattfindet, kennt der Code die Implementierung nicht. Es kennt nur die Schnittstelle und nimmt an, dass die Implementierung auch von QWidget übernommen worden wäre, wie dokumentiert. –

Antwort

1

Die zweite ist richtig. qObjectCast soll ein QObject zu "irgendetwas" umwandeln, nicht umgekehrt. Das ist, was dynamische Würfe sind für:

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

Hinweis: Die qobject_cast oben leicht mit einem dynamic_cast ersetzt werden könnte. Verwenden Sie nach Möglichkeit immer qobject_cast. Grund (aus den documentation):

Die qobject_cast() Funktion ähnlich wie bei der Standard-C++ dynamic_cast verhält() mit den Vorteilen, dass es RTTI-Unterstützung nicht erforderlich und es funktioniert über dynamische Bibliothek Grenzen.

Es verwendet Qts Metasystem (QMetaObject), um die Besetzung durchzuführen. Und außerdem scheint es viel schneller als dynamic_cast zu sein.

Der Grund, warum Sie den Qobject_cast nicht verwenden können, um die Schnittstelle zu QWidget zu konvertieren, ist, dass die Schnittstelle QObject selbst nicht erbt (und nicht über das Makro Q_OBJECT verfügt). Daher hat es kein Metaobjekt und qobject_cast kann nicht verwendet werden.

EDIT:
Eine Möglichkeit, dynamisches Gießen zu vermeiden, ist es immer, als QObject das Plugin zu halten. Wenn Sie es als Widget benötigen, werfen Sie es mit qobject_cast. Gleiches gilt für Ihre Interface. Solange Sie die Instanz als QObject speichern/weitergeben, müssen Sie niemals zu dynamic_cast wechseln.

Hinweis: Wenn Sie die Art des Plugins kennen müssen, erstellen Sie für jede Schnittstelle eine kleine Wrapper-Klasse.

+0

Ist es dann sicher, dynamic_cast() zu verwenden ?. Die Schnittstelle und der Code, der das Casting durchführt, befinden sich in einer Bibliothek (in meinem Fall von der Hauptanwendung) und die Implementierung kommt von einer anderen Bibliothek (einem Plugin). –

+0

Soweit ich weiß, ja. Weil Qt die Plugins "richtig" lädt. Zumindest für mich hat die dynamische Besetzung schon immer funktioniert. Aber wenn Sie mit dieser Lösung unangenehm sind, überprüfen Sie meinen bearbeiteten Post. – Felix