dynamic_cast, warum muss ich ihn bei einer virtuellen basis Klasse verwenden?



  • Nash26 schrieb:

    dot schrieb:

    Die wichtigste Frage von allen ist aber natürlich: Wieso musst du überhaupt von der Basis auf eine abgeleitete Klasse casten?

    Weil mir C++ es erlaubt von einer Basis Klasse zu eine abgeleiteten zu casten.

    Da hast Du wohl was falsch verstanden. Man muss nicht alles tun, was erlaubt ist.



  • Nash26 schrieb:

    Warum muss ich einen dynamic_cast verwenden, wenn ich von einer virtuellen Basis Klasse zur child Klasse casten möchte?

    Schizophren.
    Die andere Richtung ist auch nicht viel besser.
    Beides deutet natürlich auf Designfehler hin.



  • Trotz all dem

    - Mehrfachvererbung
    - polymorphic down cast

    In der Literatur zu Sowftware Designs sind diese Dinge als designteschnische Folgefehler beschrieben.

    D.h. stolperst du Du ueber diese Probleme, hasst Du im Design hoechstwahrscheinlich nen Fehler etwas früher gemacht.

    Also dynamic_cast und mehrfachvererbung sollt man immer als fettes rotes Ausrufezeichen im Quellcode betrachten, als marker das man das Design da nochmals überdenken sollte.
    2 solche aufrufezeichen sind dann schon hart ^^

    Weil mir C++ es erlaubt von einer Basis Klasse zu eine abgeleiteten zu casten.

    upcast, also child zu basis, ist durchaus gaengig und gewollt. das ist kein Problem. Das die Basisklasse immer weniger eigenschaften als wie die Ableitung hat. die Ableitung fügt also eigenschaften zur Basis hinzu.

    downcast, ist problematisch, weil du vom typ mit weniger eigenschaften auf nen Typ mit mehr eigenschaften switchen willst. du brauchst also weitere informationen um dir sicher zu sein, das nach dem cast der zeiger auch noch benutzbar ist.
    Das laeuft eigentlich dem konzept/Gedanken der Polymorphie zuwieder.

    Polymorphy heisst eigentlich nichts anderes, das du Objecten unterschiedlicher funktion an irgendeiner stelle gleichbehandeln willst ... willst du dann doch wieder unterschiede(downcast), warum dann polymorphie ?

    Kann es sein das du von ner anderen Sprache kommst, wo "ableiten" nen anderen Context hat und viel mehr verwendet wird ("Alles ist eine klasse", Java z.b.) ?

    Also Desing c++ technisch noch mal ueberdenken ...

    Ciao ...



  • ohh man oh man, eigentlich können alle Antworten bis auf die von tntnet gelöscht werden.

    Wo habe ich geschrieben das ich so eine Klassenstruktur verwende?
    Das so etwas kein gutes Design ist, sollte klar sein.

    Aber danach habe ich auch nicht gefragt, darum ging es in meiner Frage auch nicht.

    Die Frage war IMHO klar gestellt:

    Warum muss ich einen dynamic_cast verwenden, wenn ich von einer virtuellen Basis Klasse zur child Klasse casten möchte?
    

    Die Frage richtet sich zugegebenermaßen eher an Hardcore C++ Entwickler die auch auf unterster Ebene wissen was abgeht.



  • Die Antwort auf diese Frage ist einfach: Das stimmt nicht, static_cast geht auch...


  • Mod

    dot schrieb:

    Die Antwort auf diese Frage ist einfach: Das stimmt nicht, static_cast geht auch...

    Keineswegs. Ist die virtuelle Basis polymorph, kann dynamic_cast für Downcasts benutzt werden. Ist sie nicht polymorph, ist ein Downcast schlicht nicht möglich.



  • camper schrieb:

    dot schrieb:

    Die Antwort auf diese Frage ist einfach: Das stimmt nicht, static_cast geht auch...

    Keineswegs. Ist die virtuelle Basis polymorph, kann dynamic_cast für Downcasts benutzt werden. Ist sie nicht polymorph, ist ein Downcast schlicht nicht möglich.

    Stimmt, sry, hatte übersehen dass es sich um eine virtuelle Basis handeln soll. Der Grund ist natürlich, dass der Compiler in dem Fall zur Compilezeit nicht wissen kann, wie der Pointer zu verschieben ist und daher auf die Informationen in der vtable des base class subobject angewiesen ist...



  • camper schrieb:

    dot schrieb:

    Die Antwort auf diese Frage ist einfach: Das stimmt nicht, static_cast geht auch...

    Keineswegs. Ist die virtuelle Basis polymorph, kann dynamic_cast für Downcasts benutzt werden. Ist sie nicht polymorph, ist ein Downcast schlicht nicht möglich.

    Ich würde hier eher sagen:

    Ist die virtuelle Basis polymorph, MUSS dynamic_cast für Downcasts benutzt werden.
    

    Es sei denn du weißt einen weg wie es auch ohne dynamic_cast geht...

    [quote]
    Der Grund ist natürlich, dass der Compiler in dem Fall zur Compilezeit nicht wissen kann, wie der Pointer zu verschieben ist und daher auf die Informationen in der vtable des base class subobject angewiesen ist...[quote]
    Was hat es mit den pointer verschieben auf sich?
    Wie funktioniert ein cast an sich?



  • Nash26 schrieb:

    camper schrieb:

    dot schrieb:

    Die Antwort auf diese Frage ist einfach: Das stimmt nicht, static_cast geht auch...

    Keineswegs. Ist die virtuelle Basis polymorph, kann dynamic_cast für Downcasts benutzt werden. Ist sie nicht polymorph, ist ein Downcast schlicht nicht möglich.

    Ich würde hier eher sagen:

    Ist die virtuelle Basis polymorph, MUSS dynamic_cast für Downcasts benutzt werden.
    

    Es sei denn du weißt einen weg wie es auch ohne dynamic_cast geht...

    Du hast das "kann" falsch verstanden. "Kann" in dem Sinn, dass es dann überhaupt eine Möglichkeit gibt. Wenn die virtuelle Basis nämlich nicht polymorph ist, dann geht es gar nicht. Also mit keinem der verfügbaren Casts.



  • Was hat es mit den pointer verschieben auf sich?

    Solange Du das Wissen nicht anwendest, um Code zu schreiben, ist Neugier natuerlich eine gute Sache ! 😃

    Aber detailierte und generische Antworten darueber zu finden, wird schwer, weil das schon sehr in die compiler internas geht.

    Was du bereits wissen solltest:

    "Normale" Klassen (ohne virtuelle Methoden) werden nur durch ihre Member definiert. D.h. die verhalten sich wahrscheinlich wie stucts ...
    du kannst mal ne struct und ne class definieren mit gleicher Member-Signatur ! ... dann mal Instanzen boese casten, wirst sehen das wird in den meisten fallen funktionieren !
    D.h. der Klassen-Zeiger zeigt auf den Anfang der Member Daten, wo auch immer "Anfang" auf dem System definiert ist.

    Bei virtuellen Klassen kommen die Methodenpointer hinzu, sprich die vtable.
    Wo die liegt, ist nicht definiert.

    Geruechten zu folge liegt sie bei vielen Compilern vor ! den Membern.
    Bei linearen ableitungen ist es damit recht einfach. Kommen member hinzu, haengt man die hinter die Liste ... Kommen methoden hinzu, haengt man die vornedran.
    Beim casten eines zeigers aendert sich dann nur der Typ, nicht der wert ... d.h. man koennte reinterpret cast verwenden !
    und man koennte die zeiger vergleichen, um zu wissen ob es sich um die gleiche Instanz handelt ... Das wird impliziet gar ned so selten verwendet.

    Mehrfachvererbung wird dann eklig ... kannst dir vorstellen warum ?
    X ist abgeleitet von A, B und C ...
    wie koennte das der compiler aufbauen ?
    A B und C kann er nachtraglich nicht anpassen, so das sie sich einfach zusammenfuegen lassen ...

    Wenn er die VMethoden anlegt nach C-B-A, dann die Member, koennte beim cast der A zeiger bleiben ... beim B muesste er den pointer so verschieben, das die VMethoden von B relativ wieder zum pointer passen ...

    Was macht er wenn die klassen nicht nur abstract sind, sondern auch selber member haben ....
    Dann muesste er CMethoden-CMember,BMethoden-BMember,AMethoden-AMember aufbauen ... auch hier muesste er den pointer verschieben beim cast ...

    vielleicht legt er auch mehrere redundante vtables an, nur damit die geometry stimmt ?

    Das der zeiger nachm cast gleichbleibt zu jeder klasse , wird schwierig, also der vergleich auf raw ebene geht dann nimmer! du kannst nur hoffen dass er nen dynamic_cast(implizieten upcast) vorher macht ....

    Wie gesagt, wie die compiler das machen, ist nicht vorgeschrieben, es muss nur funktionieren ... deswegen ist eh vieles Spekulation. Die einzige Wahrheit aus der Sache ist, man soll sich auf das Verlassen was spezifiziert ist, und den Rest einfach ignoerieren, sonst schreibt man ganz schnell code mit undefinierten Verhalten ...

    Ciao ...



  • Wenn dich dieses Thema interessiert dann schau dir doch mal
    Inside the C++ Object Model | ISBN: 0201834545
    an. Da werden solche Sachen erklärt...



  • RHBaum schrieb:

    Bei virtuellen Klassen kommen die Methodenpointer hinzu, sprich die vtable.
    Wo die liegt, ist nicht definiert.

    Geruechten zu folge liegt sie bei vielen Compilern vor ! den Membern.

    Nein. Der VTable liegt irgendwo. 1x pro Klasse. Und als erstes Member gibt's in jedem Objekt dann einen (!) Zeiger (!) auf den VTable.

    Bei linearen ableitungen ist es damit recht einfach. Kommen member hinzu, haengt man die hinter die Liste ... Kommen methoden hinzu, haengt man die vornedran.

    linear? WTF? Im Gegensatz zu ... was? Quadratischer Ableitung?

    Und nein. Methoden hängt man auch hinten dran. Und zwar hinten an den VTable für die abgeleitete Klasse. Und das erste Member bleibt weiterhin einfach ein Zeiger auf den VTable. Deswegen verschiebt sich da in den Objekten auch nix.

    Mehrfachvererbung wird dann eklig ... kannst dir vorstellen warum ?
    X ist abgeleitet von A, B und C ...
    wie koennte das der compiler aufbauen ?

    Alles noch kein Problem. Mehrfachvererbung funktioniert wunderbar ohne dynamic_cast oder dergleichen.

    Eklig wird wirklich erst virtuelle Vererbung. Und um zu erklären wieso braucht man nichtmal VTable Zeiger oder dergleichen.

    ----

    Auch wenn ich mich damit wieder unbeliebt mache: wenn man andere belehren will, sollte man erstmal selbst verstanden haben was abgeht.


Anmelden zum Antworten