Dynamic und Static Cast? oder einfach nur ein normales Cast?
-
ok gut das hab ich alels verstanden, wenn ich nun mit dynamic cast arbeite kommt die warnung:
c:\test\AllocStruct\Transfer.h(78): warning C4541: 'dynamic_cast' used on polymorphic type 'CAllocation::CAllocNode' with /GR-; unpredictable behavior may result
und mein prgoramm stürtz ab
und 'CAllocation::CAllocNode' ist abstract
-
Dann les doch mal die Fehlermeldung...
warning C4541: 'dynamic_cast' used on polymorphic type 'CAllocation::CAllocNode' with /GR-;
Jetzt mal völlig unwissend und auf doof geraten: Du musst statt /GR- /GR+ setzen...
-
sorry... bin vll. noch nich so involliert? was ist GR- bzw. GR+ ne compitler eingstellung ?? wo stell ich das ein? habe VS 6.0
-
LordJaxom schrieb:
Dann les doch mal die Fehlermeldung...
warning C4541: 'dynamic_cast' used on polymorphic type 'CAllocation::CAllocNode' with /GR-;
Jetzt mal völlig unwissend und auf doof geraten: Du musst statt /GR- /GR+ setzen...
Gut geraten
Die Fehlermeldung besagt, daß du das Programm ohne RTTI übersetzt hast (da dynamic_cast auf RTTI basiert, kann das so nicht funktionieren). Das heißt, du mußt die RTTI einschalten, indem du /GR an den Compiler übergibst (für MSVC: Projekt->Einstellungen->Tab "C/C++"->Kategorie "Programmiersprache C++"->ein Häkchen vor "RTTI aktivieren").
-
ich komm bis "C/C++" aber ne kathegorie gibts nich... bin alles durchgegangen kann auch kein RTTI finden...
P.S.: hab die englische version...
-
Auf Englisch heißt das dann vermutlich "category" (ist eine Listbox ziemlich weit oben in dem Dialog).
-
das ist ne combo box wo ich die plattform "win32" oder "(active)win32" auswäghen kann, und dem knoten "C/C++" gibts
- General
- Optimation
- Preporcessor
- Code Generation
- Language
- Precompiled Header
- Output files
- Brows Informations
- Advanced
- Command line?????
Kategorie gibts net....
-
Da scheint das doch grundsätzlich anders aufgebaut zu sein als in der deutschen Version. Wenn ich raten müsste, würde ich mal auf 'Language' tippen.
(alternativ tippst du das /GR einfach von Hand in den Options-String ein ;))
-
hehe oh man du hast recht.. als ich "Langzage " gelesen habe.. hab ich die ganze zeit nich tan prgorammiersprache sonder an sprachauswahl für Menus und so gedacht;) .. deswegen hab ich da nichts reignshcaut
danke
-
@Boris: Was hältst du von dem Post von HumeSikkins, meinst du nicht das könnte in deinem Fall zutreffen.
-
naja am design will ich nun wirklich nich mehr dran herum schrauben..
das Ko´nzept sieht so aus:
es gibt eine Klasse 'AllocationStructure' welche eine 'AllocNode' Knoten verwaltet, diese Knoten werden in einer liste in der 'AllocationStructur' anglegt. Dabei können die Knoten in Form einer Baumstruktur angelegt werden.
Die AllocNode ist somit der Abstracte Datentyp für die neuen abgeleiten klassen, in unserem Fall B und C.
wenn ich nun einen Knoten lesen will, wird mit eine AllocNode Zeiger zurückgegeben, über diesen ich nihc auf die Methoden von B und C zurückgreifen aknnt, deswegen der cast.
Aber ok, dann frage ich mal anderes herum, unter welchen umständen muss denn ein dynamic_cast verwendet werden?? Gibt es Designs, wo man da nich drum herum kommt? Bzw. wo es Designtechnisch nicht anders umsetzbar ist?
-
BorisDieKlinge schrieb:
wenn ich nun einen Knoten lesen will, wird mit eine AllocNode Zeiger zurückgegeben, über diesen ich nihc auf die Methoden von B und C zurückgreifen aknnt, deswegen der cast.
Du musst dabei bedenken: warum hast du hier Polymorphie verwendet? Warum erben B und C von A?
idR erben B und C von A weil sie austauschbar sind. Sprich ich führe ein neues D ein dass von A erbt und ich muss keinen Strich im Code ändern.
Bei deinem Design jetzt hast du eine fixe Trennung zwischen B und C. Sie sind nicht austauschbar da sie scheinbar spezielle Sachen implementieren. Wozu also beide auf einen Haufen werfen?
Es gibt Situationen wo man es tun muss, bzw wo es praktisch ist. Aber in der Praxis sind sicher die meisten dynamic_casts einfach nur faulheit. Es ist halt eine einfache Lösung immer dynamic_cast zu verwenden. Man sollte dabei aber daran denken, dass man damit die Polymorphie wegschmeisst und im Prinzip zu altertümlichen switch-tabellen zurück fällt.
Aber ok, dann frage ich mal anderes herum, unter welchen umständen muss denn ein dynamic_cast verwendet werden?? Gibt es Designs, wo man da nich drum herum kommt? Bzw. wo es Designtechnisch nicht anders umsetzbar ist?
Ich hatte noch nie eine Situation wo ich einen dynamic_cast gebraucht habe. Ergo: möglich dass du eine dieser sehr seltenen Situationen erreicht hast wo dynamic_cast einfach die beste Lösung ist - aber das ist eher sehr unwahrscheinlich.
Einen dynamic_cast kann man zB in einer Plugin Architektur brauchen. Es gibt eine Basisplugin Klasse und alle Plugins erben davon. Nun gibt es aber verschiedene unter plugins zB Input und Output Plugins. Ein Plugin kann nun sowohl Input als auch Output oder auch beides sein. Dann kann es uU praktisch sein einmal einen dynamic_cast zu machen um zu sehen was es denn nun wirklich ist.
Die Frage stellt sich immer: warum B und C auf einen Haufen werfen, wenn man den haufen nachher wieder auftrennen will? (zu deutsch: warum eine list<A*> machen und B und C reinstecken um dann nachher nicht A rauszunehmen sondern wieder nach B und C aufzuteilen? Warum dann nicht gleich eine list<B> und eine list<C>?)
-
BorisDieKlinge schrieb:
Aber ok, dann frage ich mal anderes herum, unter welchen umständen muss denn ein dynamic_cast verwendet werden?? Gibt es Designs, wo man da nich drum herum kommt? Bzw. wo es Designtechnisch nicht anders umsetzbar ist?
Kurzfassung: Nur in absoluten Notfällen.
Etwas ausführlicher: Wenn in deinem Programm Cast-Ausdrücke (egal welche) auftreten, ist das fast immer ein Zeichen für Design-Fehler. Entweder du kennst den korrekten Typ, dann solltest du auch eine dazu passende Variable verwenden (womit der Cast unnötig wird) oder der tatsächliche Datentyp ist irrelevant, dann nimmst du einen Zeiger auf die Basisklasse und arbeitest mit Polymorphie.
Der einzige Grund für einen Cast ist imho, die Anforderungen irgendwelcher Bibliotheksfunktionen zu erfüllen, die man nicht beeinflussen kann, wie z.B sowas:
class thread_user { public: void start_thread() { AfxBeginThread(thread_func,this); } static UINT thread_func(LPVOID me) { thread_user* pThis = static_cast<thread_user*>(me); ... } };
-
CStoll schrieb:
Der einzige Grund für einen Cast ist imho, die Anforderungen irgendwelcher Bibliotheksfunktionen zu erfüllen, die man nicht beeinflussen kann
Hmm. Das ist nur eine Facette. Grundsätzlich gibt es einige Fälle, in denen man nicht sinnvoll Typen konkretisieren kann. Ein Beispiel sind z.B. GUI-Bibliotheken, in denen ein Fenster fast immer eine Controls-Collection besitzt, also irgendeinen Container, der Child-Controls enthält. Angenommen, wir wollen nun alle Buttons auf dieser Form durchlaufen und sie anklicken. Der beste Weg dafür ist folgendes:
for (Iterator<Control> c = form->controls.begin(); c != form->controls.end(); ++c) { Button* b = dynamic_cast<Button*>(c); if (b) b->perform_click(); }
Alles andere (z.B. einen Extra-Container für Buttons zu verwalten) verursacht ein enormes Zusatz-Overhead und ist selten praktisch.
-
und auch schlecht erweiterbar. Da ich die VCL verwende, kenne ich diese Situation recht gut.
-
Das Beispeil von Konrad, ist ungefähr vergleichbar mit meiner Situation... ist also schwer...
-
Shade Of Mine schrieb:
Die Frage stellt sich immer: warum B und C auf einen Haufen werfen, wenn man den haufen nachher wieder auftrennen will? (zu deutsch: warum eine list<A*> machen und B und C reinstecken um dann nachher nicht A rauszunehmen sondern wieder nach B und C aufzuteilen? Warum dann nicht gleich eine list<B> und eine list<C>?)
das ist kein haufen, sondern eine kette. was man zuerst vorne anhängt kann man zuerst hinten wieder abholen. allein das könnte der grund sein, warum boris es so macht, wie er's macht.
-
pale dog schrieb:
das ist kein haufen, sondern eine kette. was man zuerst vorne anhängt kann man zuerst hinten wieder abholen. allein das könnte der grund sein, warum boris es so macht, wie er's macht.
Du hast kein Wort von dem verstanden was ich geschrieben habe. Bitte lies es nochmal.
Ob es eine liste, ein baum, ein dreieck oder ein bunter Hund ist, ist egal. Worum es geht ist: ich schmeisse die Typinformation zum Fenster hinaus und nachher spring ich dann selber aus dem Fenster um sie wieder einzusammeln.
Da sollte sich sofort die frage stellen: warum wegschmeissen wenn ich dann den Müll druchsuchen muss um es wieder zu finden? Warum nicht einfach nicht wegschmeissen, dann spar ich mir den müll anzufassen.
-
Oder um es kurz zu machen: Man sollte Cast weitgehend vermeiden (Häufig ist ein Cast ein Anzeichen für falsches Design). Wenn man in einer Liste von polymorphen Objekten ständig casten muss ist das meistens ein fehler im Design der Basisklasse.
cu André
-
Shade Of Mine schrieb:
Ob es eine liste, ein baum, ein dreieck oder ein bunter Hund ist, ist egal.
oder ein bleicher hund?
wie auch immer, manchmal ist das ganz und gar nicht egal!Shade Of Mine schrieb:
Worum es geht ist: ich schmeisse die Typinformation zum Fenster hinaus und nachher spring ich dann selber aus dem Fenster um sie wieder einzusammeln.
Da sollte sich sofort die frage stellen: warum wegschmeissen wenn ich dann den Müll druchsuchen muss um es wieder zu finden? Warum nicht einfach nicht wegschmeissen, dann spar ich mir den müll anzufassen.der vergleich hinkt. wenn es so wäre, dann würde es kein 'dynamic_cast' geben.