C++ cast Operatoren



  • Stefan schrieb:

    @hustbaer

    In codeblocks geht's so:

    (\w+).+
    

    Ich gebe zu, es ist nicht 100% zuverlässig 😞

    Ja, sowas kann ich mir auch selbst basteln.

    foo((TypeA::TypeB) x); // cast
    bar((std::min)(a, b)) // kein cast, nur seltsame schreibweise um verwechslung mit dem #define min zu verhindern
    baz((typename X<T>::Y)(123 * 234)) // cast
    // ...
    


  • Stefan schrieb:

    Ich gebe zu, es ist nicht 100% zuverlässig 😞

    Es geht nicht nur ums Suchen. Wenn ich im Quellcode stöbere und const_cast sehe, werde ich erst mal aufmerksam und erkenne, dass hier eine potenzielle Gefahrenquelle lauert und denke vielleicht sogar über Alternativen nach. Wenn hingegen ein C-cast vorkommt, dessen primäre Aufgabe eigentlich nicht im const-wegcasten besteht, ist das schon viel mühsamer, besonders bei der Bugsuche.



  • Finder (nicht Sucher) schrieb:

    Stefan schrieb:

    Ich gebe zu, es ist nicht 100% zuverlässig 😞

    Es geht nicht nur ums Suchen. Wenn ich im Quellcode stöbere und const_cast sehe, werde ich erst mal aufmerksam und erkenne, dass hier eine potenzielle Gefahrenquelle lauert und denke vielleicht sogar über Alternativen nach. Wenn hingegen ein C-cast vorkommt, dessen primäre Aufgabe eigentlich nicht im const-wegcasten besteht, ist das schon viel mühsamer, besonders bei der Bugsuche.

    Es ist alles gesagt worden. Wer die Vorteile erkennt, nimmt eben die längere Schreibweise und wer an C hängt, macht es eben weiterhin so.



  • volkard schrieb:

    Jockelx schrieb:

    Für mich hört sich dieses Wiederfindbarkeits-Feature irgendwie konstruiert an.
    Ich hab's zumindest niemals nutzen müssen und daran wird sich auch ziemlich sicher nichts ändern.

    Geht mir genauso.

    Ich find die "neuen" einfach besser zu lesen. Bei meiner Arbeit hab ich viel mit fremdem Code zu tun, da weiß ich meistens (leider nicht immer) schneller, was der Entwickler "vor mir" gemeint hat.



  • TyRoXx schrieb:

    Es ist alles gesagt worden. Wer die Vorteile erkennt, nimmt eben die längere Schreibweise und wer an C hängt, macht es eben weiterhin so.

    OK, das ist ein Grund gegen C-Casts. Aber nicht gegen functional-style C++-Casts. Das klingt wie wenn jemand wiedermal sagt, char-Arrays seien kein C++, weil es std::string gibt.

    Die langen Casts werden im Editor blau und haben größte Signalwirkung. Das ist bei const_cast oder reinterpret_cast oder dynamic_cast auch erwünscht. Aber bei static_cast nicht! Da ist es nur blödes Rauschen, was den Lesefluß senkt und beim Debuggen nur stört.

    Deswegen nehme ich bei trivialen Casts wir von double nach int wie

    putPixel(mx+r*cos(phi),mx+r*sin(phi),red);
    

    sicher nur den Functional-Style-Cast

    putPixel(int(mx+r*cos(phi)),int(mx+r*sin(phi)),red);
    

    und nicht den langen langen

    putPixel(static_cast<int>(mx+r*cos(phi)),static_cast<int>(mx+r*sin(phi)),red);
    

    Den static_cast nehme ich, wo ein Trick dabei ist, wenn ich mich auf ein Versprechen verlasse, das an anderer Stelle im Code gegeben wurde, zum Beispiel Downcasts in der Klassenhierarchie.



  • Jockelx schrieb:

    Hast du das denn wirklich mal gebraucht?
    Für mich hört sich dieses Wiederfindbarkeits-Feature irgendwie konstruiert an.
    Ich hab's zumindest niemals nutzen müssen und daran wird sich auch ziemlich sicher nichts ändern.

    Ich habe es mal massiv vermisst, in einen sehr großen Projekt. Irgendwann wurden Umrechnungsfehler gefunden (die aber schon seit langen enthalten waren), und wir mussten fast das gesamte Projekt umwühlen (noch dazu in einer Konstellation wo auch der Debugger nicht sauber lief). Hintergrund waren einige C-Style Casts die verdammt schwer zu finden waren (u.A. auch wegen den alternativen Steibweisen int(...), (int)... und weil sie auch vielen Funktionsdeklarationen in dem Projekt ähnlich sahen.

    Wenn du einmal ein Projekt mit etwa 1 Millionen Codezeilen durchsuchen musstest, und dir zudem der Debugger nicht viel weiterhilft, wirst du danach nicht mehr von "konstruierten" Featuren sprechen.

    Die Fehlersuche hat mehr als eine Woche gedauert, und ob diese Konvertierungen wirklich die einzig problematischen waren, sei dahin gestellt.



  • asc schrieb:

    Hintergrund waren einige C-Style Casts die verdammt schwer zu finden waren (u.A. auch wegen den alternativen Steibweisen int(...), (int)...

    Der Functional-Style-Cast ist immer noch kein C-Style-Cast.
    Wie soll man solche Postings denn ernst nehmen? Ihr macht es mir schon recht schwer.



  • asc schrieb:

    Wenn du einmal ein Projekt mit etwa 1 Millionen Codezeilen durchsuchen musstest, und dir zudem der Debugger nicht viel weiterhilft, wirst du danach nicht mehr von "konstruierten" Featuren sprechen.

    ex falso quod libet.
    Es bleibt für mich ein Problem Anderer Leute.



  • Ich stimme Volkard zu.

    const_cast: Absolut spitze 👍
    dynamic_cast: Super 👍
    reinterpret_cast: Brauch ich im Low-Level oft, besser als die alten Casts, da es auch auf Äquivalenzen von Handles o.ä. hinweist 👍
    static_cast: Manchmal ganz dolle, wenn ich z.B. void*s umcaste nutze ich ihn immer, aber oft sieht ein Functional-Cast einfacher besser aus (wegen Konstruktor-Ähnlichkeit) o. ich belasse es sogar bei impliziten Typenkonvertierungen, um die Lesbarkeit der Codelogik zu verbessern. Die alten Casts übernehmen bei mir nur das, was auch nur ein static_cast hätte tun können.



  • Ad aCTa schrieb:

    dynamic_cast: Super 👍 .

    Da hier alle vom dynamic_cast schwärmen: Habt ihr den jemals gebraucht?



  • Ja. Stichwort: Multiple Dispatching.



  • Michael E. schrieb:

    Ad aCTa schrieb:

    dynamic_cast: Super 👍 .

    Da hier alle vom dynamic_cast schwärmen: Habt ihr den jemals gebraucht?

    Natürlich habe ich das! Um den Typ festzustellen und dann per if je nach Typ...
    ~
    Muß ich das wirklich noch weiter ausführen?
    Es ist doch schon jahrelang her.
    Ich war jung und brauchte das Geld!
    Haben wir nicht alle schon mal...
    So haben es damals aber alle gemacht.
    ~



  • Biolunar schrieb:

    Ja. Stichwort: Multiple Dispatching.

    Ist Dispatching per dynamic_cast nicht ziemlich out? Siehe volkard.



  • Michael E. schrieb:

    Biolunar schrieb:

    Ja. Stichwort: Multiple Dispatching.

    Ist Dispatching per dynamic_cast nicht ziemlich out? Siehe volkard.

    Single Dispatching per dynamic_cast ist sogar eine Sünde.
    Double-Dispatching per dynamic_cast eigentlich auch.
    Triple-Dispatching habe ich noch nie gebraucht, vielleicht ist es da angemessen. Nee, kann ja nicht. Da muß man langsam anfangen und Hashtables oder sowas nehmen und braucht einen int als Typidentifizierer, den macht man natürlich herkömmlich per virtual int getTypeID() oder per return reinterpret_cast<int*>(this);//liest bei MSVC den vptr, hihi



  • > reinterpret_cast<int*>(this);//liest bei MSVC den vptr, hihi

    xD Echt?


  • Administrator

    volkard schrieb:

    Deswegen nehme ich bei trivialen Casts wir von double nach int wie

    putPixel(mx+r*cos(phi),mx+r*sin(phi),red);
    

    sicher nur den Functional-Style-Cast

    putPixel(int(mx+r*cos(phi)),int(mx+r*sin(phi)),red);
    

    und nicht den langen langen

    putPixel(static_cast<int>(mx+r*cos(phi)),static_cast<int>(mx+r*sin(phi)),red);
    

    Naja, gäbe ja noch die Möglichkeit:

    int x = static_cast<int>(mx + r * cos(phi));
    int y = static_cast<int>(mx + r * sin(phi));
    
    putPixel(x, y, red);
    

    Aber ich würde grundsätzlich sagen und das ist in diesem Thread eher untergegangen, dass man mit den neuen C++ Cast Werkzeuge für gezielte Konvertierungsaufgaben erhält. Der C Cast ist einfach ein Hau-Drauf-Cast. Der alte C++ Cast sollte man im übrigen nicht mit dem C Cast verwechseln. Der alte C++ Cast erlaubt die Konvertierung nur zu einfachen Typen. Die einzigen erlaubten Typen sind somit:
    char , wchar_t , bool , short , int , long , void , float , double , long double und natürlich die jeweils möglichen signed oder unsigned Typen. Zeiger kann man damit nicht konvertieren! Es ist somit ein abgeschwächter static_cast . Daher halte ich ihn, gerade in dem von volkard gezeigten Einsatzgebiet, durchaus für eine mögliche Option, da er meiner Meinung nach keine mögliche Fehlerquelle wie der C Cast darstellt.

    Ich persönlich verwende grundsätzlich fast nur die neuen C++ Cast. Dies auch mit der Begründung der Wiederauffindung, auch wenn ich selber dies als ein sehr schwaches Argument ansehe. Benötigt habe ich es bisher eher nicht. Stören tut es mich aber auch nicht, da ich:
    a) sowieso sehr selten Casts überhaupt einsetze.
    b) alle Formeln auseinander nehme und zum Beispiel ganz sicher nicht noch etwas im Funktionsaufruf ausrechne. Daher sieht es meistens wie meine vorgeschlagene Möglichkeit des Aufrufs von putPixel aus. Zum Teil ist nicht mal mehr eine Berechnung in den Klammern des Casts, sondern einfach eine Zwischenresultatsvariable.

    Glossary (speziell für Volkard 🤡)
    Neue C++ Cast: static_cast, dynamic_cast, reinterpret_cast, const_cast
    Alter C++ Cast: Functional-Style-Cast
    C Cast: (T)value

    Grüssli


  • Mod

    Dravere schrieb:

    Der alte C++ Cast erlaubt die Konvertierung nur zu einfachen Typen. Die einzigen erlaubten Typen sind somit:
    char , wchar_t , bool , short , int , long , void , float , double , long double und natürlich die jeweils möglichen signed oder unsigned Typen. Zeiger kann man damit nicht konvertieren! Es ist somit ein abgeschwächter static_cast .

    hm...

    typedef int* LPDONTTOUCHME;
    *LPDONTTOUCHME(17+25)=0xdeadbeef;
    

  • Administrator

    camper schrieb:

    Dravere schrieb:

    Der alte C++ Cast erlaubt die Konvertierung nur zu einfachen Typen. Die einzigen erlaubten Typen sind somit:
    char , wchar_t , bool , short , int , long , void , float , double , long double und natürlich die jeweils möglichen signed oder unsigned Typen. Zeiger kann man damit nicht konvertieren! Es ist somit ein abgeschwächter static_cast .

    hm...

    typedef int* LPDONTTOUCHME;
    *LPDONTTOUCHME(17+25)=0xdeadbeef;
    

    Das ist mir sehr neu. Nun frage ich mich allerdings, wieso dann sowas nicht geht:

    *int*(17+25)=0xdeadbeef;
    

    Problem von der Syntax her? Doch welches? Wieso nur den Umweg über typedef erlauben?
    Auch noch im Standard nachgelesen, aber aus dem werde ich bei dem Punkt nicht so ganz schlau.

    Grüssli



  • asc schrieb:

    Jockelx schrieb:

    Hast du das denn wirklich mal gebraucht?
    Für mich hört sich dieses Wiederfindbarkeits-Feature irgendwie konstruiert an.
    Ich hab's zumindest niemals nutzen müssen und daran wird sich auch ziemlich sicher nichts ändern.

    Ich habe es mal massiv vermisst, in einen sehr großen Projekt. Irgendwann wurden Umrechnungsfehler gefunden (die aber schon seit langen enthalten waren), und wir mussten fast das gesamte Projekt umwühlen

    Was für ein unordentliches Projekt muss das sein?
    Das Projekt, an dem ich momentan beteiligt bin, ist nur geringfügig kleiner, aber sollten da Umrechnungsfehler auftreten,
    dann müsste ich sicher keine 1 Millionen Zeilen durchsuchen, weil irgendwo -scheinbar weiss keiner wo- irgendwie wild rumgecastet wird.
    Da liegt der Fehler wohl weniger am falsch verwendeten cast.
    Aber okay, jetzt haben mehrer geschrieben, dass sie ihre Projekte nach casts durchsuchen müssen.
    Also von mir aus ist das dann halt auch nich ein Punkt, der für C++-Cast spricht.
    Aber ich hoffe wir sind uns einig, dass es einer der letzten Punkte ist, den man anführen sollte.


Anmelden zum Antworten