[C/C++] const auf integrale typen in einer Funktion sinnvoll?



  • DEvent schrieb:

    C++ kennt doch Exceptions, oder? Wieso wurde nicht einfach vollgendes gemacht:

    dynamic_cast macht btw. genau das. es wirft ne exception wenn der cast fehlschlägt. und warum statische casts nix werfen sollte eigentlich klar sein.

    unterschiedliche sachen die unterschiedliche arbeit machen und unterschiedliche auswirkungen haben sehen halt unterschiedlich aus.

    was ist zB bei

    T* t=(T*)f;

    absolut mehrdeutig solange du nicht genau weisst was f ist...



  • Shade Of Mine schrieb:

    DEvent schrieb:

    C++ kennt doch Exceptions, oder? Wieso wurde nicht einfach vollgendes gemacht:

    dynamic_cast macht btw. genau das. es wirft ne exception wenn der cast fehlschlägt.

    nicht bei pointern, da gibt er einfach 0 zurück, wenn es fehlschlägt. warum dieses unterschiedliche verhalten? könnte er nicht in beiden fällen eine exception werfen?
    🙂



  • ;fricky schrieb:

    nicht bei pointern, da gibt er einfach 0 zurück, wenn es fehlschlägt. warum dieses unterschiedliche verhalten? könnte er nicht in beiden fällen eine exception werfen?
    🙂

    Exceptions nur in ausnahmefällen.
    Und jetzt denk mal an die möglichen Anwendungen für dynamic_cast. Dann wirst du sehen dass es meistens zum testen verwendet wird ob eine bestimmte beziehung zwischen dem objekt und einer klasse besteht.

    Wenn du dich ein bisschen mit der Materie befassen würdest, wüsstest du sowas.



  • Shade Of Mine schrieb:

    ;fricky schrieb:

    nicht bei pointern, da gibt er einfach 0 zurück, wenn es fehlschlägt. warum dieses unterschiedliche verhalten? könnte er nicht in beiden fällen eine exception werfen?
    🙂

    Exceptions nur in ausnahmefällen.
    Und jetzt denk mal an die möglichen Anwendungen für dynamic_cast. Dann wirst du sehen dass es meistens zum testen verwendet wird ob eine bestimmte beziehung zwischen dem objekt und einer klasse besteht.

    Wenn du dich ein bisschen mit der Materie befassen würdest, wüsstest du sowas.

    Andere Sprachen haben ein instance_of.
    Wenn ein Cast einfach eine exception werfen wuerde, so koennte man sich diese xxx_cast sparen und alle Casts haetten ein konsistentes Verhalten.



  • Shade Of Mine schrieb:

    Exceptions nur in ausnahmefällen.

    man hört immer, exceptions werden in c++ dem prüfen von rückgabewerten vorgezogen. wieso plötzlich diese ausnahme, dass beim dynamic-cast, auf pointer angewendet, der rückgabewert getestet werden muss?

    Shade Of Mine schrieb:

    Und jetzt denk mal an die möglichen Anwendungen für dynamic_cast. Dann wirst du sehen dass es meistens zum testen verwendet wird ob eine bestimmte beziehung zwischen dem objekt und einer klasse besteht.

    hat c++ nicht 'typeid' um sowas zu testen?
    🙂



  • ;fricky schrieb:

    Shade Of Mine schrieb:

    Exceptions nur in ausnahmefällen.

    man hört immer, exceptions werden in c++ dem prüfen von rückgabewerten vorgezogen. wieso plötzlich diese ausnahme, dass beim dynamic-cast, auf pointer angewendet, der rückgabewert getestet werden muss?

    hören ist gut, zuhören solltest du auch noch.

    ;fricky schrieb:

    Shade Of Mine schrieb:

    Und jetzt denk mal an die möglichen Anwendungen für dynamic_cast. Dann wirst du sehen dass es meistens zum testen verwendet wird ob eine bestimmte beziehung zwischen dem objekt und einer klasse besteht.

    hat c++ nicht 'typeid' um sowas zu testen?
    🙂

    [/quote]nein. typeid gibt Informationen über den am weitesten abgeleiteten Typ, der interessiert in cross-cast-Fällen überhaupt nicht.



  • DEvent schrieb:

    Andere Sprachen haben ein instance_of.

    Genau darauf habe ich gewartet.
    Es zeigt nämlich wunderschön dass hier im Kreis argumentiert wird.

    In C++ gibt es eben kein instanceof sondern nur einen dynamic_cast der eben testet ob a eine instanz von b oder von einer von b abgeleiteten klasse ist.

    Wenn es einen instanceof operator geben würde, hätten wir hier die exakt selbe diskussion nur dass eine vereinheitlichung gefordert werden würde, weil ja dynamic_cast schon diese Aufgabe erfüllt.

    Man kann sich nicht immer alles zurecht drehen: erst ist vielfalt schlecht, dann ist sie wieder gut, dann ist redundanz besser und dann ist sie wieder schlecht.

    Wenn ein Cast einfach eine exception werfen wuerde, so koennte man sich diese xxx_cast sparen und alle Casts haetten ein konsistentes Verhalten.

    Es gibt nur einen cast der eine exception werfen kann: dynamic_cast. Denn alle anderen cast arten sind zur Compile Zeit validierbar. Es macht keinen Sinn dass ein static_cast oder const_cast oder reinterpret_cast eine exception wirft.

    Und der einzige cast wo es sinn machen kann, wirft genau dann eine exception wenn es sinn macht (und wenn es keinen sinn macht, dann wirft er keine). Und damit ist eine konsistenz zwischen allen casts nicht mehr realisierbar.

    Das ist ziemlich ideal.

    Man muss ja nurmal an Java denken:

    if(!(o instanceof Foo))
      return false;
    
    Foo bar = (Foo) o;
    

    versus

    bar = dynamic_cast<Foo*>(o);
    if(!bar) return false;
    

    Ich habe hier enorm das Gefühl dass einfach nur Mainstream Techniken promoted werden und alles andere ist schlecht. Ob ich jetzt instanceof oder dynamic_cast mache ist komplett egal. Ich könnte auch ein hühott() machen, namen sind schall und rauch.

    Die C++ casts dagegen bieten eben vorallem im Vergleich zu Java einen enormen Vorteil: sie sind mächtiger.

    Denn Java bietet im Prinzip nur eine mischung aus static_cast und dynamic_cast an. Einen const_cast braucht java nicht, da es keine const-correctness gibt und man dort statt const eben clone() verwendet (und clone kann man nicht rückgängig machen). Einen reinterpret_cast hat Java nicht und auch nichts vergleichbares. Ergo gibt es in Java ja nur dynamic_cast und static_cast. Und da man in Java nicht sagen kann "vertrau mir, ich weiss was ich tue" ist ein static_cast ziemlich unnötig.

    Denn ein static_cast kann für up und downcasts verwendet werden (einzig für cross casts nicht). Und es spart die lookups in der vtable. Diese Möglichkeit gibt es in Java nicht (design entscheidung), ergo ist static_cast auf primitive typen limitiert und dynamic_cast auf referenzen. Somit ist jeder cast aus dem kontext heraus immer eindeutig und es gibt keinen grund einen anderen cast zu verwenden.

    C++ ist komplexer. Deshalb verwendet man ja in C++ auch checked_casts statt dynamic_casts wenn es um up/down casts geht. ein checked_cast ist ein static_cast der in der debug version dynamic_cast verwendet um den cast zu validieren. Ist wunderschön schnell und man braucht keine vtable lookups.

    Die Wahl zu haben ist immer etwas gutes. Es ist nicht immer das einfachste und C++ ist sicher nicht die simpelste Sprache der Welt, aber C++ bietet dem Programmierer eben Power Tools. Die unterschiedlichen Casts sind eben solche Tools die trivial zu meistern sind und uU relevante Vorteile bieten. Meistens erhöhen sie nur die Lesbarkeit des Codes, aber in gewissen Situationen sind sie eben unersetzbar.

    Aber wie gesagt: brauchen tut C++ diese Casts nicht. C Casts würden reichen wenn man ihnen die dynamic_cast Fähigkeit gegeben hätte (hat man nicht getan da C Casts böse sind).



  • Und wer die Casts überhaupt nicht mag, kann immer noch auf Assembler seiner Wahl umsteigen. Dort hat man nur die CPU Register und die ganzen Rohdaten, die vorzeichenlos oder vorzeichenbehaftet oder gar eine Adresse sein können, je nach dem, wie man gerade Lust hat, sie zu interpretieren und man darf alles ineinander, übereinander, durcheinander kopieren, verschieben, zuweisen und was weiss ich noch damit anstellen, alles ohne Casts, daher Assembler eben 😉



  • Shade Of Mine schrieb:

    Es gibt nur einen cast der eine exception werfen kann: dynamic_cast. Denn alle anderen cast arten sind zur Compile Zeit validierbar. Es macht keinen Sinn dass ein static_cast oder const_cast oder reinterpret_cast eine exception wirft.

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.

    Shade Of Mine schrieb:

    ...aber C++ bietet dem Programmierer eben Power Tools. Die unterschiedlichen Casts sind eben solche Tools die trivial zu meistern sind und uU relevante Vorteile bieten.

    jetzt übertreibst du aber. diese 'power tools' sind c++'s mitgelieferter reparaturset, eigens auf c++ selbst zurechtgeschnitten. nichts anderes als hilfsmittel, damit sich der c++ programmierer wieder aus dem gröbsten schlamassel ziehen kann. und wem das nicht reicht, der holt sich einfach'n paar casts dazu, wie polymorphic_downcast, lexical_cast und was es da sonst noch für abgefahrene dinge gibt.
    🙂



  • ;fricky schrieb:

    Shade Of Mine schrieb:

    Es gibt nur einen cast der eine exception werfen kann: dynamic_cast. Denn alle anderen cast arten sind zur Compile Zeit validierbar. Es macht keinen Sinn dass ein static_cast oder const_cast oder reinterpret_cast eine exception wirft.

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.

    bitte geh woanders trollen.



  • Natürlich ist const unnötig. Aber eigentlich ist das ganze Typsystem unnötig. 🙂

    Aber ich bin fest davon überzeugt, dass ein striktes Typsystem für besseren Code sorgt. Und zu einem strikten Typsystem gehört für mich auch die Präzisefassung von Typeigenschaften. Sei dies nun der genaue Wertebereich oder die Konstantheit. ADA macht das hier besonders schön. In C++ ist das so aber auch möglich.

    Mich nervt es immer, wenn ich Code in einer untypisierten Sprache ändere und an einer ganz anderen Stelle fliegen dann auf einmal irgend welche Laufzeittypeerrors. Bis man solche Probleme aufgelöst hat kann einige Zeit verstreichen. Aber auch in typisierten Sprachen gibt es viele Spielmöglichkeiten, wo man über so etwas stolpert. Seien das nun Sicherheitslücken durch Integeroverflows oder Werte die sich auf einmal irgend wo ändern. Sicher kommt man auch ohne aus. Aber nicht umsonst hat ADA ein derartiges Typekonzept bekommen.



  • ;fricky schrieb:

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein[...]

    1. C++ ist da nicht anders als C: "Ich weiß was ich tue, also compiler, lass mich einfach machen". Und nichts anderes sagt ein reinterpret_cast aus. Wenn du also explizit dem compiler den Mund verbietest, darfst du dich nicht wundern, wenn er nicht meckert.
    2. Das Argument der schwachen Typisierung geht am Thema vorbei. Dabei geht es um implizite casts, nicht um die expliziten über die wir gerade reden. UND DIE HAT C AUCH.

    Fazit: Du argumentierst bei C++ gegen etwas, das du in C selbst verteidigst und offensichtlich gut findest.

    Bist du eventuell Politiker?



  • ;fricky schrieb:

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten.

    Nein. Denn reinterpret_cast heisst "vertrau mir, ich weiss was ich mache". Das darf keinen Fehler produzieren.



  • otze schrieb:

    Fazit: Du argumentierst bei C++ gegen etwas, das du in C selbst verteidigst und offensichtlich gut findest.

    naja, C ist nun mal sehr low-level, sowas wie 'ne portable assemblersprache. in dem bereich, in dem C verwendet wird (maschinennah, effizient, speicherschonend), muss man sich machmal über's typsystem hinwegsetzen und seltsame tricks anwenden. solche eigenschaften sind aber im high-level bereich weniger sinnvoll, weil sie einfach zu 'mächtig' sind und man sich damit über wichtige konzepte hinwegsetzen kann, an denen sprachdesigner lange getüftelt haben, um die sprache halbwegs sicher zu machen. ich würde z.b. um Java einen grossen bogen machen, wenn man da arrays in objekt-referenzen casten, einen boolean zu 'nem int addieren oder einen string überschreiben könnte.

    Shade Of Mine schrieb:

    ;fricky schrieb:

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten.

    Nein. Denn reinterpret_cast heisst "vertrau mir, ich weiss was ich mache". Das darf keinen Fehler produzieren.

    ok, dann löst eben das OS 'ne exception aus, sagte ich ja schon.
    🙂



  • ;fricky schrieb:

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.

    Und wie soll entschieden werden, was sinnvoll ist und was nicht? Und wer kann den Laufzeitoverhead für so einen Schwachsinn vertreten? Abgesehen davon crashen Konvertierungen nicht, sondern höchstens der nachfolgende Zugriff.

    ;fricky schrieb:

    naja, C ist nun mal sehr low-level, sowas wie 'ne portable assemblersprache. in dem bereich, in dem C verwendet wird (maschinennah, effizient, speicherschonend), muss man sich machmal über's typsystem hinwegsetzen und seltsame tricks anwenden. solche eigenschaften sind aber im high-level bereich weniger sinnvoll, weil sie einfach zu 'mächtig' sind und man sich damit über wichtige konzepte hinwegsetzen kann, an denen sprachdesigner lange getüftelt haben, um die sprache halbwegs sicher zu machen. ich würde z.b. um Java einen grossen bogen machen, wenn man da arrays in objekt-referenzen casten, einen boolean zu 'nem int addieren oder einen string überschreiben könnte.

    C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen. Wenn man auf hohem Abstraktionslevel entwickelt, braucht man sowas wie reinterpret_cast kaum, wieso also eine Exception?

    ;fricky schrieb:

    ok, dann löst eben das OS 'ne exception aus, sagte ich ja schon.

    Du hast wohl Exceptions nicht ganz verstanden. Die sind nämlich nicht primär dazu da, sämtliche Programmlogikfehler zu beheben. Bei reinterpret_cast macht ein "Rumprobieren, wenns schief läuft, fliegt eine Exception" wenig Sinn. Ein fehlerhaft eingesetztes reinterpret_cast ist nahezu immer ein Programmierfehler, der auch zur Laufzeit nicht vernünftig behoben werden kann. Man lässt das Programm lieber crashen und passt den Code so an, dass er funktioniert.

    P.S.: Das, was rüdiger angetönt hat, ist eins der Standardargumente gegen C++ - "man brauchts nicht". Klar, ist wunderbar anwendbar auf Mehrfachvererbung, Operatorüberladung, Zeigerarithmetik, Const-Correctness und sonst alle C++-Features, die andere Sprachen nicht bieten "und ja auch ohne auskommen". Das ideale Argument™, was will man mehr?



  • Nexus schrieb:

    ;fricky schrieb:

    naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.

    Und wie soll entschieden werden, was sinnvoll ist und was nicht? Und wer kann den Laufzeitoverhead für so einen Schwachsinn vertreten? Abgesehen davon crashen Konvertierungen nicht, sondern höchstens der nachfolgende Zugriff.

    vielleicht konfigurierbar über'n compiler-switch oder so. RTTI lässt sich ja auch ein- und ausschalten. klar können konvertierungen auch schon selber abschmieren. dazu brauchte noch nicht mal 'nen dynamic cast, der sich durch die vererbungsliste hangelt und plötzlich auf einen 0-pointer trifft.

    Nexus schrieb:

    C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen.

    doch mit einschränkungen: http://www.mikrocontroller.net/articles/C_vs_C-Plusplus

    Nexus schrieb:

    P.S.: Das, was rüdiger angetönt hat, ist eins der Standardargumente gegen C++ - "man brauchts nicht". Klar, ist wunderbar anwendbar auf Mehrfachvererbung, Operatorüberladung, Zeigerarithmetik, Const-Correctness und sonst alle C++-Features, die andere Sprachen nicht bieten "und ja auch ohne auskommen". Das ideale Argument™, was will man mehr?

    aber im prinzip stimmt es, z.b:
    mehrfachvererbung -> sehr selten sinnvoll, fördert schlechtes design
    operatorüberladung -> geringer nutzen, wird oft falsch verwendet
    zeiger/zeigerarithmetik -> in low-level sprachen sinnvoll, in höheren sprachen nicht
    const-correctness -> idiomatisch in C++, in der realität ausserhalb von c++ aber ohne bedeutung.
    🙂



  • ;fricky schrieb:

    aber im prinzip stimmt es, z.b:
    mehrfachvererbung -> sehr selten sinnvoll, fördert schlechtes design
    operatorüberladung -> geringer nutzen, wird oft falsch verwendet
    zeiger/zeigerarithmetik -> in low-level sprachen sinnvoll, in höheren sprachen nicht
    const-correctness -> idiomatisch in C++, in der realität ausserhalb von c++ aber ohne bedeutung.
    🙂

    Ach, halt doch einfach die Klappe. Du hast keinen Schimmer von C++ und Deine Aussagen sind größtenteils falsch.



  • ;fricky schrieb:

    Nexus schrieb:

    C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen.

    doch mit einschränkungen: http://www.mikrocontroller.net/articles/C_vs_C-Plusplus

    Der Link war wohl ein Eigentor, zumindest sehe ich hier keinen einzigen Nachteil von C++ gegenüber C. In allen aufgezählten Punkten ging C++ als Sieger hervor in Bezug darauf, dass es Funktionalität liefert die man in C händisch nachbauen muss oder gar nicht hat. Und was ganz wichtig ist: wenn man sie nicht benutzt, dann kosten sie nichts.



  • ;fricky schrieb:

    klar können konvertierungen auch schon selber abschmieren.

    EPIC fail.
    reinterpret_cast kann nicht abschmieren.

    gib dir bitte mühe beim trollen, mittlerweile kann meine oma deine "argumente" widerlegen... uU vl mal mit der materie befassen...?



  • Shade Of Mine schrieb:

    reinterpret_cast kann nicht abschmieren.

    cast in einen Typ, für den der Operand nicht hinreichend ausgerichtet ist?


Anmelden zum Antworten