dynamische Besetzung mit Schnittstellen

7

Ich habe eine Klasse mit implementiert 2 Schnittstellen und erbt 1 Klasse. So sieht es im Allgemeinen so aus:

%Vor%

Es gibt einen Punkt im Code, wo ich eine IB * habe, aber könnte wirklich eine A * verwenden. Ich hatte gehofft, dass eine dynamische Besetzung das mögen würde:

%Vor%

Leider funktioniert das nicht. Gibt es einen richtigen Weg, dies zu tun? Oder sollte ich eine Arbeit implementieren? Ich habe darüber nachgedacht, sowohl IB als auch IC virtuell von A zu erben, aber IIRC habe das letzte Mal versucht, dass es einige Komplikationen gab, die es unerwünscht machten.

Irgendwelche Gedanken?

BEARBEITEN : Oh ja, das ist Teil einer Plugin-API, also habe ich leider keinen direkten Zugang zum T -Typ, wo ich A * brauche. Mein Beispiel hat dann nebeneinander, aber wie gesagt, es ist komplizierter. Grundsätzlich habe ich 2 gemeinsame Bibliotheken. T und T1 (wo ich ein IB * habe) sind beide Klassen, die eine Plugin API implementieren und intern in den Shared Libraries sind.

Zur Verdeutlichung: Hier ist ein konkreteres Beispiel für meine typischen Plugins (sie befinden sich in separaten Bibliotheken):

Plugin A:

%Vor%

Plugin B:

%Vor%

BEARBEITEN : Ich vermute, dass das Problem darin liegt, dass sich pluginA und pluginB in verschiedenen gemeinsam genutzten Bibliotheken befinden. Vielleicht überschreitet der rtti keine Modulgrenzen. Ich denke, das könnte der Fall sein, weil die Beispiele der Leute in meinen Tests gut zu funktionieren scheinen. Insbesondere hat pluginB keine "typeinfo for PluginA" wenn ich ein "nm" mache. Dies könnte der Kern des Problems sein. Wenn dies der Fall ist, muss ich es einfach umgehen, entweder durch virtuelle Vererbung oder eine virtuelle Funktion cast_to_qobject() in einer meiner Schnittstellen.

    
Evan Teran 14.01.2009, 05:12
quelle

5 Antworten

3

Ich fand es schließlich heraus, Daniel Paul hatte Recht, dass ein "seitwärts dybnamic_cast "sollte erlaubt sein. Mein Problem war, weil mein Code gemeinsame Bibliotheken miteinbezieht. Die Typinfo von PluginA war in PluginB nicht verfügbar. Meine Lösung bestand darin, RTLD_NOW und RTLD_GLOBAL zu meinem Ladeprozess hinzuzufügen

technisch war es

%Vor%

weil ich das Plugin-System von Qt verwende, aber den gleichen Unterschied. Diese Flags erzwingen, dass alle Symbole aus geladenen Bibliotheken sofort aufgelöst werden und für andere Bibliotheken sichtbar sind. Daher die Typinfo für jeden verfügbar machen, der sie benötigt. Der dynamic_cast funktionierte wie erwartet, sobald diese Flags vorhanden waren.

    
Evan Teran 24.01.2009, 02:51
quelle
7

Hat jede Klasse mindestens eine virtuelle Methode? Wenn nicht, gibt es dein Problem. Das Hinzufügen eines virtuellen Destruktors zu jeder Klasse sollte das Problem beheben.

Folgendes hat glücklich für mich funktioniert:

%Vor%

BEARBEITEN:

Nach all den neuen Informationen und dem ungewöhnlichen Verhalten (Ihr Code sollte einfach funktionieren!), hilft Ihnen folgendes? Ich habe eine Schnittstelle namens IObject eingeführt und verwende virtuelle Vererbung, um sicherzustellen, dass es nur eine Kopie dieser Basisklasse gibt. Können Sie jetzt zu IObject und dann zu A konvertieren?

%Vor%

Ich behaupte nicht, dass es die richtige Lösung ist, aber es könnte ein paar Informationen darüber geben, was vor sich geht ...

    
Daniel Paull 14.01.2009 05:37
quelle
5
  

Gibt es einen richtigen Weg, dies zu tun? Oder sollte ich eine Arbeit implementieren? Ich habe darüber nachgedacht, ob sowohl IB als auch IC virtuell von A her erben, aber IIRC das letzte Mal, als ich versuchte, dass es einige Komplikationen gab, die es unerwünscht machten.

Ich nehme dann an, dass die Definitionen von IB und IC unter Ihrer Kontrolle stehen.

Es gibt die Art, wie COM-Schnittstellen unter Windows funktionieren. Sie tun, was Sie wollen, d. h .:

  • Cast von einer Schnittstelle zu einer anderen
  • Die Implementierung ist für den Aufrufer undurchsichtig
  • Nur die Implementierung weiß, welche Schnittstellen sie implementiert

Tun Sie dies, Sie können etwas wie (ungeprüfter Code voraus) machen ...

%Vor%

Eine viel einfachere, stärker kodierte Version wäre:

%Vor%     
ChrisW 14.01.2009 05:41
quelle
3

Wirf zuerst ein T * und dann A:

%Vor%

Wenn IB im Allgemeinen zu A umsetzbar sein soll, dann sollte IB vielleicht von A erben.

Bearbeiten: Ich habe es gerade versucht und es funktioniert - beachten Sie, dass E zum Zeitpunkt der Erstellung der Hauptmethode unbekannt ist.

%Vor%     
Eclipse 14.01.2009 05:16
quelle
1

Ich habe mich in letzter Zeit auch mit dem gleichen Problem beschäftigt. Weitere Informationen finden Sie im GCC-FAQ-Eintrag:

Ссылка

Neben der Anweisung dlopen mit RTLD_ * -Flags können einige Inkarnationen dieses Problems auch vom Linker gelöst werden, siehe seine -E- und -Bsymbolic-Optionen.

    
Gert 20.07.2009 13:54
quelle

Tags und Links