Fortschrittsanzeige



  • Wo ist denn dann bitteschön der Unterschied zwischen den beiden Zeilen? Wo ist denn dann der Vorteil von static_cast gegenüber dem ()-cast? Mal abgesehen davon, das ersteres C++ ist?

    Wenn es dich interessiert, lies doch bitte einfach mal den Artikel. Ich poste doch nicht einen Link aus purer langeweile. Und wenn ich schon einen Link poste, muss ich den Inhalt doch nicht auch noch vorkauen.

    By the way, ich bin immer bereit Neues zu lernen und mich mit Neuen Dingen auseinanderzusetzen

    Tatsächlich. Also den Eindruck machst du *in dieser* Situation nicht auf mich.
    Ich sehe hier eigentlich nur verbohrtheit, was die neuen Casts angehet.

    Hab mal einen Suchlauf über das VC98-Verzeichnis machen lassen. Kein einziges Mal dynamic_cast gefunden...

    Du weißt aber sicher, dass die meisten Dateien im VC98-Verzeichnis älter als der C++-Standard sind. Und das es damals noch *gar keinen* dynamic_cast gab. Sicher, das weißt du.
    Du weißt bestimmt auch, dass RTTI damals noch gar nicht standardisiert war und das deshlab z.B. die MFC ihre eigene Form des RTTIs mitbringt.

    IEntweder der Pointer ist auch ein Zeiger auf die Klasse, in die ich Casten will, oder er ist NULL.

    Das garantiert dir nur der dynamic_cast.

    Und mich durch Klassenhierarchien durchwälzen tue ich auch nicht, dazu gibt's virtuelle Funktionen und ähnliches.

    Ein großartiges Argument, vorallem wenn es in einem Atemzug mit den C-Casts genannt wird.

    Wenn ich also mit dynamic_cast hier nicht weiterkomme, was macht dann der Ich-arbeite-strikt-nach-C++-Programmierer? Aufgeben? Oder muss er sich mit veralteten Funktionalitäten abfinden?

    Sich genau informieren, warum es nicht geht wie es gehen *sollte*. Wenn es überhaupt nicht anders geht, den Vorschlaghammer rausholen. Einen Kommentar dranschreiben und sich bei MS beschweren, dass ihre Lib kaputt ist.

    Wenn es geht, aber vielleicht Geschwindigkeitseinbußen mitsichbringt, *profilen* um zu schauen, ob diese relevant sind. Wenn es nicht anders geht, Vorschlaghammer rausholen und einen Kommentar dranschreiben.

    Aber wie man es auch dreht und wendet. Ich würde sagen, man sollte erst *wissen* was man tut, bevor man den Vorschlaghammer rausholt und undefiniertes Verhalten heraufbeschwört. Einfach mal aus Verdacht alles kurz und kleinzuschlagen ist meiner Meinung nach keine gute Strategie.

    B* b;
    #ifdef _DEBUG
    b = dynamic_cast<B*>( a);
    #else
    b = reinterpret_cast<B*>( a);
    #endif

    Und schon wieder falsch. Bei all dem Sarkasmus und der Ignoranz die ihr hier an den Tag legt, solltet ihr es wenigstens *richtig* machen.
    Ein reinterpret_cast ist *nicht* für downcasts geeignet. Wenn du sicher bist, dass hinter dem a-Zeiger ein B-Objekt steckt heißt die Antwort
    *static_cast*. Die Einschränkungen habe ich schon zwölf-mal geschrieben. Und sie gilt für alle casts außer dem dynamic_cast.
    Der Code sollte also wenn so aussehen:

    B* b;
    #ifdef _DEBUG
      b = dynamic_cast<B*>( a);
    #else
      b = static_cast<B*>( a);
    #endif
    

    Ähnlichen Code wirst du in vielen professionellen Programmen finden. Mal abgesehen davon, dass natürlich vernünftige Coding-Styles Präprozessor-ifs *innerhalb* von Methoden verbieten.

    #ifdef _DEBUG
    #define MYCAST( class, ptr) (dynamic_cast<class*>( ptr));
    #else
    #define MYCAST( class, ptr) (reinterpret_cast<class*>( ptr));
    #endif

    Oder einfach bei der bekannten Syntax bleiben:

    // VC6-Workaround aus Gründen der Übersicht weggelassen.
    #ifdef _DEBUG
    template <class Dest, class Source>
    inline Dest MyCast(Source p)
    {
        return dynamic_cast<Dest>(p);
    }
    #else
    template <class Dest, class Source>
    inline Dest MyCast(Source p)
    {
        return static_cast<Dest>(p);
    }
    #endif
    

    Richtig, daran hab ich auch schon gedacht. Was würde ein Sortieralgorithmus für 1.000.000 Elemente mit Verwendung von dynamic_cast wohl länger brauchen?

    Warum würde ich wohl ein dynamic_cast in einem Sortieralgorithmus anwenden? Da würde ich mir mal eher um mein kaputtes Design Gedanken machen.

    Also gehe ich recht in der Annahme (hoffentlich diesmal ), dass reinterpret_cast und der ()-cast genau das gleiche machen?
    Und static_cast castet nur zwischen Zeigertypen die in einer Klassenhierarchie untereinanderstehen, aber ohne Runtime-Checking, während dynamic_cast das gleiche macht, nur mit Runtime-Checking?

    Nö. Der C-cast ist eine Mischung aus static_cast, reinterpret_cast, const_cast und in C++ eigentlich verbotenen Sachen.

    Der static_cast macht kurz gesagt alle Konvertierungen zwischen S und T möglich, für die es eine umgekehrt implizite Konvertierung von T nach S gibt.
    Dazu gehört unter anderem der downcast.

    [ Dieser Beitrag wurde am 31.03.2003 um 11:20 Uhr von HumeSikkins editiert. ]



  • Das klingt ja alles sehr gut, hab mich gerade kurz mal informatiert und mein "Verdacht" hat sich bestätigt. Ein Informatik-Studi! 😉

    Da ich trotz meiner "Vorschlaghammer"-Programmierung bisher noch nie (und ich programmiere schon sehr lange) undefiniertes Verhalten hatte, wüsste ich nicht, was an meiner "Vorschlaghammer"-Programmierung grundlegend falsch ist. Oder warum was anderes verwenden sollte, wenn es auch weiterhin funktioniert.

    Und zu meinem Satz

    Entweder der Pointer ist auch ein Zeiger auf die Klasse, in die ich Casten will, oder er ist NULL.

    der mit

    Das garantiert dir nur der dynamic_cast.

    beantwortet wurde, muss ich mich vielleicht deutlicher Ausdrücken:

    Wenn ich eine Funktion habe, wie z.B.

    void CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
    }
    

    und ich weiß, dass lParam ein NHMDR* ist, dann kann ich mir hundertprozentig sicher sein, dass

    NMHDR* pInf = (NMHDR*)lParam;
    

    nicht zu undefiniertem Verhalten führt! Und wenn ein lParam NULL ist, dann ist auch pInf gleich NULL. Dann füge ich noch ein ASSERT(pInf != NULL) hinzu, und schon weiß ich, dass alles Ok ist. Hab noch nie das Problem mit falschen Zeigern gehabt. Entweder sie waren Ok oder NULL. Und wenn die nicht sein durften, dann hat mir das das ASSERT gesagt und der Fehler wurde bereinigt, nach mehrfachem Testen wurde die Release kompiliert. Irgendwann trat dann doch mal ein Fehler auf, dann hab ich die Debug-Version genommen, den Fehler nachvollzogen und das Problem beseitigt. Und alles ohne dynamic_cast, static_cast, reinterpret_cast und was es sonst noch so alles gibt.



  • Das klingt ja alles sehr gut, hab mich gerade kurz mal informatiert und mein "Verdacht" hat sich bestätigt. Ein Informatik-Studi!

    Ja und? Was willst du damit sagen? Ich habe weder C++ entwickelt noch den C++ Standard geschrieben.
    Ich kann dir aber in diesem Fall sagen, wie es ist und was im Standard steht. Wenn du ein Problem damit hast, dir etwas von einem "Informatik-Studi" sagen zu lassen, dann sag das. In diesem Fall werde ich selbstverständlich nicht mehr auf deine Postings eingehen.

    Da ich trotz meiner "Vorschlaghammer"-Programmierung bisher noch nie (und ich programmiere schon sehr lange) undefiniertes Verhalten hatte

    Wie willst du das beurteilen, wenn du an den Regeln die der C++ Standard aufstellt nicht interessiert bist? Schau dir doch den Verlauf des Threads einfach mal an. Ich behaupte mal, dass es keinen C++ Programmierer gibt, der nicht schonmal über undefiniertes Verhalten gestolpert ist. Ob er dies bemerkt hat steht auf einem ganz anderen Blatt.

    Wenn ich eine Funktion habe, wie z.B.

    void CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
    }
    und ich weiß, dass lParam ein NHMDR* ist, dann kann ich mir hundertprozentig sicher sein, dass

    NMHDR* pInf = (NMHDR*)lParam;
    nicht zu undefiniertem Verhalten führt!

    Richtig. Ich rede ja auch von Situationen wo du *nicht* hunderprozentig weißt, von welchem Typ das Objekt ist, auf das ein Basisklassenzeiger verweist. Es geht hier um Laufzeitpolymorphie und nicht um irgendwelche Krücken namens LPARAM. Hier könntest du überhaupt keinen dynamic_cast einsetzen, selbst wenn du es wolltest.

    In Situationen wo du *vorher genau* weißt und *wissen musst*, von welchem Typ ein Objekt ist, du aber nur eine Basisklassenreferenz hast, stellt sich die Frage, warum du dieses Wissen überhaupt aufgibst. Wenn du auf den Cast angewiesen bist, verhält sich der Code nicht polymorph. In diesem Fall stellt sich die Frage, warum er dann so aufgebaut ist. Da gibt es zwei Möglichkeiten: Entweder man verwendet gleich den passenden Typ oder man packt die Funktionalität in virtuelle Methoden und kann damit auf den downcast verzichten.



  • Ich hab überhaupt kein Problem damit, dass Du ein Inf-Studi bist. Und dass Du den C++-Standard weder entwickelt noch geschrieben hast, ist mir auch klar. Sollte weder eine Anspielung sein noch eine Kritik. Da Du Dich aber so strikt nach dem C++-Standard richtest (was sicherlich auch lobenswert ist), hast Du Dich nunmal als Inf-Studi "verdächtig" gemacht. Mehr nicht.

    Wie ich das beurteilen will? Ganz einfach: Undefiniertes Verhalten ist, wenn ein Programm nicht das macht, was es machen soll. Und - wie schon gesagt - meine Projekte laufen alle fehlerfrei und kleine MickeyMouse-Programme sind's auch nicht.
    Und ich behaupte einfach mal, dass sich an meinen Programmen durch einsetzen der hier heiß diskutierten Operatoren nichts verbessern wird.

    Mit den "Krücken" wie LPARAM muss man bei der Windows-Programmierung nun mal leben. Oder schickst Du dann MS auch eine eMail, wenn Du einen LPARAM in einen NMHDR* konvertieren musst?

    In meinen Programmen vermeide ich grundsätzlich das casten von einer Basisklasse zu höheren Klassen, wenn ich mir NICHT sicher sein kann, was das für eine Klasse ist, die mir da über den Weg läuft (bei dem ursprünglichen Problem mit dem CProgressCtrl kann ich mir sicher sein). Dafür verwende ich virtuelle Funktionen.

    Und wenn ich virtuelle Funktionen überschreibe und ihr wird eine Zeiger auf ein Objekt einer Basisklasse übergeben, dann schreibe ich auch nur Code, wo ich Funktionen der Basisklasse verwende.



  • dynamic_cast braucht man auch eigentlich fast nirgendwo, wenn man normale programme schreibt 🙂



  • Vorsicht @grins, solche Aussagen können Seitenlange Abhandlungen zur Folge haben... 😉



  • Original erstellt von Shaggy:
    Wie ich das beurteilen will? Ganz einfach: Undefiniertes Verhalten ist, wenn ein Programm nicht das macht, was es machen soll.

    sorry wenn ich mal dein Weltbild durcheinanderbringe 😉

    Undefiniertes Verhalten entsteht an den Stellen, an denen der Standard keine Aussage über das Verhalten macht, aber nicht von den Implementierern fordert, dass sie a) entweder das Verhalten dokumentieren (implementation-defined) oder b) aus einer Menge von möglichen sinnvollen Alternativen nach eigenem Gutdünken eine auswählen, ohne sie zu dokumentieren (unspecified). Das heißt nicht, dass undefiniertes Verhalten sich durch Abstürze oder falsche Ergebnisse oder sonstige äußerlich beobachtbare Effekte äußern muß, sondern lediglich, dass das Verhalten des Programms nicht mehr dem entspricht, das der Standard festschreibt.



  • Nö, mein Weltbild wankt nicht! 😉 Gut, das ist wahrscheinlich die Definition des "undefinierten Verhaltens" wie sie der C++-Standard macht. Alles eine Definitionssache. Dass ich mir undefiniertes Verhalten einfangen kann, wenn ich just-for-fun meine Klassen hin und her caste, und dann auf Speicher zugegriffen wird, der nicht initialisiert, etc. ist, ist mir auch bekannt. Ich betrachte dynamic_cast und Co. mal als zusätzliche Helferlein. Die Programmierer vor dieser Zeit sind auch gut ohne zurecht gekommen.



  • Es läuft immer darauf hinaus, dass du keine Garantien hast, wenn du Spezifikationen verletzt. Egal ob es jetzt der C++-Standard ist oder sonstwas.



  • Ergo kann/ soll ich prinzipiell die ganze MFC wegschmeißen, da es keine Garantien gibt?



  • . Da Du Dich aber so strikt nach dem C++-Standard richtest (was sicherlich auch lobenswert ist), hast Du Dich nunmal als Inf-Studi "verdächtig" gemacht. Mehr nicht.

    Kapier ich immer noch nicht. Was hat ein Inf-Studi mit dem C++-Standard zu tun?
    Für mich impliziert das sehr stark eine Wertung. So nach dem Motto: Akademiker vs. "in the trenches"-coder. Und das wäre in meinen Augen völlig unpassend.

    Ergo kann/ soll ich prinzipiell die ganze MFC wegschmeißen, da es keine Garantien gibt?

    Nö. Schließlich macht die MFC bestimmte Garantien. Du solltest aber die MFC wegschmeißen, wenn du an einer guten OO-Bibliothek interessiert bist. Aber darum geht's hier nicht.

    Was du in meinen Augen etwas mindern könntest ist deine Ignoranz und dein Sarkasmus. Aussagen wie:

    Vorsicht @grins, solche Aussagen können Seitenlange Abhandlungen zur Folge haben...

    oder

    Die Programmierer vor dieser Zeit sind auch gut ohne zurecht gekommen.

    haben meiner Meinung nach in einer technischen Diskussion nichts zu suchen und sind völlig überflüssig.
    Es soll Zeiten gegeben haben, in denen man völlig ohne Computer gut zurecht gekommen ist. Nur was hat das mit dem Thema zu tun?

    [ Dieser Beitrag wurde am 31.03.2003 um 16:22 Uhr von HumeSikkins editiert. ]



  • Nein, aber die Garantien nutzen solange sie nutzbar sind.

    Beispiel:
    Nutzbar sind sie nicht: Wenn sie nicht vorhanden sind, wie bei dem LParam. Da gehts wohl nicht anderst.

    Oder die Sicherheit in Zeitkritischen dingen zu viel Zeit kostet

    Beispiel:

    ka , aber wenn man an die 8020 Regel denkt (von mir aus auch 7030 oder 9010) kann man schon sehr selten die Zeit als Argument haben.

    Das würde bei dem Progressbar bedeuten das man die chance hätte das als Controlvariable einzufügen (oder wie auch immer das heisst....)

    Es wird aber niemand dazu gezwungen. Der mit der Controlvariable hat in einem sehr w*****einlich, in einem zeitunkritischen Moment, mehr Rechenzeit verbraten. Rene hat weiter oben beschrieben was u.a. dann passiert, wobei schreibarbeit nie ein Argument sein darf.

    Jedoch braucht dieser Anwender keine Angst vor änderungen vor Compilerspezifischen dingen haben die im nachhinein viel Entwicklungszeit kosten können.

    (Bevor es jemand anderst sagt: Nur weil es im standard so steht muß es sich nicht so verhalten, die Implementierungen sind auch nicht fehlerfrei und können bei neuer Compilerversion zu überraschungen führen.)

    Desweiteren hat der mit der COntrolvariable den Vorteil das Control wesentlich leichter auszutauschen. Ich habe mir die Header angesehen und es gibt eine Handvoll Klassen die keine Member haben. Möchtze ich aber nun z.B. das ProgressBar COntrol durch ein anderes ersetzen das ka. wo her ist, geht hier eine Aufwendige prüfung los ob ich nun noch den c-style cast machen kann (nebst anderen dingen). Und wenn dies dann über mehrere Vererbungen geht kann das aufwendig werden. Der anwender mit der Controlvariable hat es hier wesentlich einfacher - er muß sich darüber keine gedanken mehr machen. Er tauscht die Klasse einfach aus.

    Aber das sollte ja hier auch garnicht diskussion werden. Ich hatte erst behauptet das casten geht nicht und ist falsch. Das ganze ist Ansichtssache und ich denke hier kommt man auf keine gemeinsame Meinung. Ich habe die hintergründe verstanden warum der c-style cast verwendet wird (thx @ll).

    Aus diesen Beiträgen dürften die vor / nachteile und eventuelle Risiken deutlich geworden sein. Aus diesem Wissen nun etwas zu machen bleibt jedem Programmierer selbst überlassen.

    [ Dieser Beitrag wurde am 31.03.2003 um 16:33 Uhr von Knuddlbaer editiert. ]



  • Wenn, dann ist es schon Akademiker vs. Akademiker. Und was hat ein Inf-Studi mit C++-Standard zu tun? Sehr viel, alle die ich kenne (und nicht gerade wenig), programmieren derart strikt, weil sie es im Grundstudium so eingebleut bekommen.

    Deine Ignoranz ist mindestens ebenso groß wie meine, schliesslich vertreten wir hier beide vollkommen konträre Standpunkte und jeder beharrt darauf. Mit dem Unterschied, dass ich Deinen akzeptiere, umgekehrt leider nicht. Ist mir aber egal.
    Und was den Sarkasmus angeht, wer keinen Spaß versteht, sollte sich nicht mit anderen Menschen unterhalten. Humor ist wenn man trotzdem lacht.

    Vielleicht solltest Du das von Dir zitierte Sturgeon's Law selbest zu Herzen nehmen.



  • Und was hat ein Inf-Studi mit C++-Standard zu tun? Sehr viel, alle die ich kenne (und nicht gerade wenig), programmieren derart strikt, weil sie es im Grundstudium so eingebleut bekommen.

    Ich hab nicht studiert 😃 Ich halte mich nur so strickt an den Standard weil ich in meiner Programmierzeit mit einigen Compilern arbeiten musste und der Standard überall (mehr oder weniger) definiert ist. Hat mir viel Arbeit gespart.

    Und nun : Keep Smiling 🤡

    [ Dieser Beitrag wurde am 31.03.2003 um 16:43 Uhr von Knuddlbaer editiert. ]



  • Wenn, dann ist es schon Akademiker vs. Akademiker. Und was hat ein Inf-Studi mit C++-Standard zu tun? Sehr viel, alle die ich kenne (und nicht gerade wenig), programmieren derart strikt, weil sie es im Grundstudium so eingebleut bekommen.

    Komisch. Die Informatikstudenten die ich kenne (Braunschweig, Potsdam, Berlin, Köln), haben im Studium überhaupt nicht Programmieren gelernt. Vielleicht etwas Algorithmen-Kunde. Mit Sicherheit aber keine konkrete Programmiersprache.
    Studenten die sich für's Programmieren interessieren, lernen das zu Hause oder in einer Firma.
    Das ist übrigens einer meiner größten Kritikpunkte am Informatikstudium.

    Deine Ignoranz ist mindestens ebenso groß wie meine, schliesslich vertreten wir hier beide vollkommen konträre Standpunkte und jeder beharrt darauf

    Mit dem Unterschied, dass ich mich in diesem Fall mit den *Fakten* auf beiden Seiten auskenne. Ich habe mich also auf Grund von Wissen *gegen* den C-Cast entschieden. Du aufgrund von Unwissenheit *gegen* die C++-Casts.
    Das ist es ja auch genau was ich kritisiere. Ich kritsiere nicht, dass du den C-Cast nutzt. Mir geht es darum, dass du nicht weißt, welche Semantik welche Cast hat und welche Regeln es gibt. Und ich kritisieren, dass du nicht daran interessiert bist diese Unwissenheit abzulegen.

    Mit dem Unterschied, dass ich Deinen akzeptiere, umgekehrt leider nicht

    Augen und Ohren verschließen, sich gegenüber Fakten taub zu stellen und diese nicht nachlesen zu wollen ist für mich keine Form von Akzeptanz.

    Und was den Sarkasmus angeht, wer keinen Spaß versteht, sollte sich nicht mit anderen Menschen unterhalten. Humor ist wenn man trotzdem lacht.

    Wenn ich lachen will, ess ich ein Lachgummi. Und wenn ich über etwas technisches diskutiere, besitzt Lachen für mich nicht die höchste Priorität.



  • meine Güte ... ich hab nicht Alle Seiten gelesen aber am Anfang dieses Threads stand ziemlich viel Schwachsinn über Vererbung und völlig Normale casts von Klassen - typisches Forengeblubber eben .... dazu einmal das Bild hier Beschauen, das fegt den kompletten Unsinn vom Tisch (die Unkenntlich gemachte Klasse beinhaltet ein CProgressCtrl)

    Sofern man nicht mit Data-Alignment und Konsorten rumpfuscht wird ein solcher Cast in 99,9999999999% aller Fälle funktionieren denn fast alle Controls sind auch CWnd's

    http://i.imagehost.org/0274/blubblubblub.jpg
    Google: site:msdn.microsoft.com Hierarchy Chart


Anmelden zum Antworten