Problem mit Auflösung virtueller Funktionen
-
SALOMON schrieb:
Außerdem wäre nen dynamic-cast noch schön, da kannste auch prüfen, ob sich obj wirklich in Klasse4 überführen lässt (wirft bad_cast, wenn es sich nich umwandeln lässt).
Mein dynamic_cast gibt in dem Fall NULL zurück.
-
richtig so wars, hab mich vertan

EDIT: Hab gerade nomma nachgeschaut... bei Referenzen gibts nen bad_cast (weil auch logischerweise kein 0 zurückgegeben werden kann) und bei Zeigern ist es die 0.
-
Vermutlich führen deine C-Style Casts zu diesem Fehler. Ein C-Style Cast kann sich wie ein dynamic_cast verhalten, wenn alle entsprechenden Header vorher inkludiert wurden. Steht vorher aber nur so etwas wie "class MeineKlasse;", wird wie in C gecastet, ohne die Adresse anzupassen (sofern nötig).
Es ist also nicht möglich nur durch ansehen des Casts zu entscheiden, ob alles richtig gemacht wird.Grundsätzlich sollten in einem C++ Programm keine C-Style Casts verwendet werden.
Lars
-
Danke für eure Unterstützung, mein Problem lies sich damit so halbwegs lösen.
Der vergessene Pointer-Stern war natürlich ein Tippfehler im Posting.
Was das dynamische casting angeht, so verwende ich jetzt eine Mischung aus C-casts und dynamic_cast-Anweisungen. (Ist notwendig, da andernfalls zwar mein Zugriff auf die Basisklasse funktioniert, welche bisher versagt hat, dafür klappts bei reinem dynamic_cast bei den anderen nicht mehr)
Ist zwar keine schöne Lösung, aber so gehts wenigstens. In Zukunft werde ich dann darauf achten, mich soweit möglich an den dynamic_cast zu halten.
Also nochmals Danke.
-
Welche "anderen" Casts gehen nicht? dynamic_cast funktioniert nur bei abgeleiteten Typen also nur mit Downcasting. Sonst gibts da noch static_cast um sowas wie float in int zu konvertieren, const_cast um ein konstantes Objekt veränderbar zu machen und reinterpret_cast... wobei reinterpret_cast so ziehmlich alles frisst, wenn du einen Zeiger hast (z.B. void*) und den dann in einen Zeiger eines anderen Typs konvertieren willst.
-
Galatea schrieb:
Was das dynamische casting angeht, so verwende ich jetzt eine Mischung aus C-casts und dynamic_cast-Anweisungen. (Ist notwendig, da andernfalls zwar mein Zugriff auf die Basisklasse funktioniert, welche bisher versagt hat, dafür klappts bei reinem dynamic_cast bei den anderen nicht mehr)
Dann machst du etwas falsch. C-Style Casts sind nicht notwendig, es geht immer mit den C++ Casts.
Lars
-
was ich meinte war ungefähr das folgende
Klasse1* pClass1=CreateObject();//die zurückgegebene Instanz hat eigentlich den Typ Klasse4* Klasse4* pClass4_C=(Klasse4*)pClass1;//C-Style cast zu Klasse4 pClass4_C->Initialize();//funktioniert pClass4_C->Methode1();//funktioniert nicht Klasse4* pClass4_Dyn=dynamic_cast<Klasse4*>(pClass1);//dynamisch gecastet pClass4_Dyn->Initialize();//funktioniert nicht (die entsprechende vftable wird an der falschen Stelle gesucht) dynamic_cast<Klasse2*>(pClass4_Dyn)->Methode1();//funktioniert auch nicht pClass4_Dyn->Methode1();//funktioniertich vermute es liegt am internen Verhalten der DLL, was ich aber nicht wesentlich verändern kann. Ich halte mir deshalb beide Versionen des gecasteten Pointers und nutze jeweils diejenige, die funktioniert.
solltest du zufällig eine Idee haben, warum das einmal geht und das andere mal nicht, würde ich mich dennoch über einen Hinweis freuen
-
Was soll der Cast eigentlich?
Klasse1* CreateObject() { return (Klasse1*)new Klasse4(); }Mach das mal so:
Klasse1* CreateObject() { return new Klasse4; }
-
Galatea schrieb:
ich vermute es liegt am internen Verhalten der DLL, was ich aber nicht wesentlich verändern kann.
Was mir noch immer nicht klar ist: Wurde die DLL mit der gleichen Compilerversion erzeugt?
-
Ich habe keine Einflussmöglichkeiten auf den Quellcode in der DLL und auch nicht auf die verwendete Compilerversion (VC2008). In meinem Projekt (der "Applikation") bin ich auf Grund von Rahmenbedingungen auf Visual Studio 2010 angewiesen, da auch das .Net Framework 4.0 zur Anwendung kommt. Also sind DLL und Applikation nicht mit der selben Compilerversion erstellt (und das lässt sich auch nicht ändern).
Was den scheinbar überflüssigen Cast angeht, so kann ich nicht beantworten, warum er verwendet wird. Ich kann lediglich bestätigen, dass er wirklich so im Quelltext steht.
-
Galatea schrieb:
Also sind DLL und Applikation nicht mit der selben Compilerversion erstellt...
Okay, dann erübrigt sich auch jeder Versuch einer Hilfe, da die Compilerversionen vermutlich eine inkompatible binäre Darstellung haben (Ein riesiges Manko von C++ ist die fehlende Binärkompatibilität).
Einzige Lösung die mir einfällt:
Wrapper-DLL unter VS2008 schreiben, die alle Aufrufe in eine C-Schnittstelle umwandelt, den C-Schnittstellen sind im Gegensatz zu C++ Schnittstellen unproblematisch. Oder einen COM-Wrapper...
-
Wie ich bereits am Anfang beschrieben habe, kann das eigentlich nicht das Problem sein, da alles problemlos funktioniert, wenn ich die Debugversion der DLL verwende. Nur eine in der Releaseversion kompilierte DLL verursacht den Fehler, was mich zum Schluss kommen lässt, dass es ein Konfigurationsproblem bzw. ein Compilerschalter sein müsste.
-
Galatea schrieb:
Wie ich bereits am Anfang beschrieben habe, kann das eigentlich nicht das Problem sein, da alles problemlos funktioniert, wenn ich die Debugversion der DLL verwende. Nur eine in der Releaseversion kompilierte DLL verursacht den Fehler, was mich zum Schluss kommen lässt, dass es ein Konfigurationsproblem bzw. ein Compilerschalter sein müsste.
Debug und Release Dateien sind oftmals unterschiedlich.
Von daher kann es sein, dass du eine gesonderte DLL für den Releasebuild benötigst.
-
asc schrieb:
Galatea schrieb:
Also sind DLL und Applikation nicht mit der selben Compilerversion erstellt...
Okay, dann erübrigt sich auch jeder Versuch einer Hilfe, da die Compilerversionen vermutlich eine inkompatible binäre Darstellung haben (Ein riesiges Manko von C++ ist die fehlende Binärkompatibilität).
Einzige Lösung die mir einfällt:
Wrapper-DLL unter VS2008 schreiben, die alle Aufrufe in eine C-Schnittstelle umwandelt, den C-Schnittstellen sind im Gegensatz zu C++ Schnittstellen unproblematisch. Oder einen COM-Wrapper...Mit Interfaces (Klasse mit nur rein virtuellen Methoden) ist die Interoperabilität auch zwischen verschiedenen Versionen eines Kompiler gegeben.
(Siehe "Imperfect C++" von Matthew Willson).Simon
-
Dass sich die Ausgabedateien bei Debug- und Releaseversion unterscheiden, ist mir klar. Soweit ich das bisher verstanden hatte, hängt das doch aber damit zusammen, dass jede Konfiguration einen eigenen Satz von (einstellbaren) Optionen hat. Würde man diese Optionen zwischen den Konfigurationen angleichen, so müsste nach meinem Verständnis das selbe Ergebnis rauskommen, da ja letztendlich in beiden Fällen der selbe Compiler verwendet wird - nur die angegebenen Compiler Switches unterscheiden sich. (wobei hier mit Compiler nicht das Entwicklungswerkzeug, sondern die Anwendung (vcbuild.exe oder so ähnlich) selbst gemeint ist)
Irre ich mich darin denn grundlegend?