casten



  • Hi,..

    Be Precise

    Ja, genau das mache ich ja. Ich sage explicit und precise wie der compiler
    ein datensegment zu behandeln hat. Und stellt euch vor: Das mit C_Casts!

    Die this ptr adjustage im casting von multiblen derivaten muss
    selbstverständlich berücksichtigt werden.

    Gehen wir doch mal das Dokument gemeinsam durch:

    Zuerst das wichtigste,...

    ...But note that I said that an offset is “sometimes” required. The way
    objects are laid out and the way their addresses are calculated varies
    from compiler to compiler. That means that just because your “I know
    how things are laid out” casts work on one platform doesn’t mean
    they’ll work on others. The world is filled with woeful programmers
    who’ve learned this lesson the hard way.

    gucken wir uns doch mal das beispiel an:

    class SpecialWindow: public Window { // derived class
    public:
    virtual void onResize() { // derived onResize impl;
    static_cast<Window>(*this).onResize(); // cast *this to Window,
    // then call its onResize;
    // this doesn’t work!
    ... // do SpecialWindow-
    } // specific stuff
    ...
    };
    

    Funktioniert net, also ohne C++ style cast....

    class SpecialWindow: public Window { // derived class
    public:
    virtual void onResize() { // derived onResize impl;
    Window::onResize(); 
    ... // do SpecialWindow-
    } // specific stuff
    ...
    };
    

    Und ein weiters beispiel:

    class Window { ... };
    class SpecialWindow: public Window {
    public:
    void blink();
    ...
    };
    typedef // see Item 13 for info
    std::vector<std::tr1::shared_ptr<Window> > VPW; // on tr1::shared_ptr
    VPW winPtrs;
    ...
    for (VPW::iterator iter = winPtrs.begin(); // undesirable code:
    iter != winPtrs.end(); // uses dynamic_cast
    ++iter) {
    if (SpecialWindow *psw = dynamic_cast<SpecialWindow*>(iter->get()))
    psw->blink();
    }
    

    Das gleiche für dynamic_cast bei der blink member fkt, braucht man nicht, dafür hat man die polymorphie,..

    class Window {
    public:
    virtual void blink() {} // default impl is no-op;
    ... // see Item 34 for why
    }; // a default impl may be
    // a bad idea
    class SpecialWindow: public Window {
    public:
    virtual void blink() { ... }; // in this class, blink
    ... // does something
    };
    typedef std::vector<std::tr1::shared_ptr<Window> > VPW;
    VPW winPtrs; // container holds
    // (ptrs to) all possible
    ... // Window types
    for (VPW::iterator iter = winPtrs.begin();
    iter != winPtrs.end();
    ++iter) // note lack of
    (*iter)->blink(); // dynamic_cast
    

    Weil es so schön war, gucken wir uns nochmal seine aussage über die performance an:

    For example, at least one common implementation is based in
    part on string comparisons of class names. If you’re performing a
    dynamic_cast on an object in a single-inheritance hierarchy four levels
    deep, each dynamic_cast under such an implementation could cost you
    up to four calls to strcmp to compare class names. A deeper hierarchy
    or one using multiple inheritance would be more expensive.

    Diskutieren wir doch mal gemeinsam die C++ Cast types

    ■ const_cast is typically used to cast away the constness of objects. It
    is the only C++-style cast that can do this.
    ■ dynamic_cast is primarily used to perform “safe downcasting,” i.e.,
    to determine whether an object is of a particular type in an inheritance
    hierarchy. It is the only cast that cannot be performed using
    the old-style syntax. It is also the only cast that may have a
    significant runtime cost. (I’ll provide details on this a bit later.)
    ■ reinterpret_cast is intended for low-level casts that yield implementation-
    dependent (i.e., unportable) results, e.g., casting a pointer
    to an int. Such casts should be rare outside low-level code. I use it
    only once in this book, and that’s only when discussing how you
    might write a debugging allocator for raw memory (see Item 50).
    ■ static_cast can be used to force implicit conversions (e.g., non-const
    object to const object (as in Item 3), int to double, etc.). It can also be
    used to perform the reverse of many such conversions (e.g., void*
    pointers to typed pointers, pointer-to-base to pointer-to-derived),
    though it cannot cast from const to non-const objects. (Only
    const_cast can do that.)

    const_cast const Ist nur für den zu kompilierenden kontext
    (strucktur konsistenz und lebenzeitprüfung zur kompilierzeit) und nicht für
    die ausführung des Sources relevant. (Einfach mal assembly anschauen)
    D.h. verwendet man ein const_cast so hat man einen struckturellen fehler in der
    Deklaration oder Definition.

    dynamic_cast Weg damit,wozu gibt es polymorphie,...

    reinterpret_cast
    A) Wozu gibt es Casting member Operatoren
    und 😎 (MSDN) The reinterpret_cast allows the pointer to be treated as an
    integral type. The result is then bit-shifted and XORed with itself to produce
    a unique index (unique to a high degree of probability). The index is then
    truncated by a standard C-style cast to the return type of the function.

    static_cast
    (MSDN) Consequently, static_cast can do the inverse of implicit conversions, in
    which case the results are undefined. It is left to the programmer to verify
    that the results of a static_cast conversion are safe.

    This behavior also applies to types other than class types. For instance,
    static_cast can be used to convert from an int to a char. However, the
    resulting char may not have enough bits to hold the entire int value. Again, it
    is left to the programmer to verify that the results of a static_cast
    conversion are safe.
    -- So, und was ist der unterschied zum C_Cast ???

    Wie ich gesagt habe: Der maintance unterschied ist das highlighting.
    Man darf aber ie vergessen das alignment der Objecte bei den Casts zu prüfen.

    Mal gucken wem ich jetzt wieder auf den Schlipps getreten bin 😃

    Freu mich auf response 😉



  • zeusosc schrieb:

    Be Precise

    Ja, genau das mache ich ja. Ich sage explicit und precise wie der compiler
    ein datensegment zu behandeln hat. Und stellt euch vor: Das mit C_Casts!

    Das tust Du nicht. Denn die Bedeutung eines C-style Cast ist abhängig vom Kontext. Je nach Kontext kann es ein static_cast, const_cast, reinterpret_cast, etc etc etc oder sogar eine Kombination daraus sein. Das gefährliche daran ist, dass es kompilieren kann und etwas anderes macht, als das, was der Programmierer sich dabei gedacht hat. Mit den C++-style Casts hast Du die Möglichkeit, genau das auszudrücken, was Du wilclst. Wenn Du beispielsweise einen static_cast brauchst, aber einen C-style Cast benutzt und versehentlich das const entfernst, kann Dir der Compiler das nicht als Fehler anstreichen. Ein C-style Cast ist die "Ich konvertiere alles irgendwie"-Brechhammer-Methode, die evnetuell Dinge tut, die Du nicht willst und die mit C++-style-Casts abgefangen werden können, weil sie jeweils restriktiver sind.

    Und so in etwa steht das auch in Deinem zitierten Link!

    zeusosc schrieb:

    Die this ptr adjustage im casting von multiblen derivaten muss
    selbstverständlich berücksichtigt werden.

    Gehen wir doch mal das Dokument gemeinsam durch:

    Zuerst das wichtigste,...

    ...But note that I said that an offset is “sometimes” required. The way
    objects are laid out and the way their addresses are calculated varies
    from compiler to compiler. That means that just because your “I know
    how things are laid out” casts work on one platform doesn’t mean
    they’ll work on others. The world is filled with woeful programmers
    who’ve learned this lesson the hard way.

    Mit anderen Worten: reinterpret_cast (oder ein C-style Cast der einen reinterpret_cast enthält, obwohl man ihm es nicht ansehen kann) ist gefährlich.

    zeusosc schrieb:

    gucken wir uns doch mal das beispiel an:

    class SpecialWindow: public Window { // derived class
    public:
    virtual void onResize() { // derived onResize impl;
    static_cast<Window>(*this).onResize(); // cast *this to Window,
    // then call its onResize;
    // this doesn’t work!
    ... // do SpecialWindow-
    } // specific stuff
    ...
    };
    

    Funktioniert net, also ohne C++ style cast....

    Dieser cast erzeugt ein neues Window-Objekt per Slicing. Wenn es das ist, was Du willst, dann ist es natürlich richtig. Ansonsten, hättest Du auch noch hinter Window ein & setzen können, um das Subobjekt von *this zu adressieren. Ziehe in Betracht, dass Du C++-style Casts nicht verstanden haben könntest.

    zeusosc schrieb:

    Und ein weiters beispiel:

    class Window { ... };
    class SpecialWindow: public Window {
    public:
    void blink();
    ...
    };
    typedef // see Item 13 for info
    std::vector<std::tr1::shared_ptr<Window> > VPW; // on tr1::shared_ptr
    VPW winPtrs;
    ...
    for (VPW::iterator iter = winPtrs.begin(); // undesirable code:
    iter != winPtrs.end(); // uses dynamic_cast
    ++iter) {
    if (SpecialWindow *psw = dynamic_cast<SpecialWindow*>(iter->get()))
    psw->blink();
    }
    

    Das Beispiel hat nichts mit "C++ style" vs "C style" cast zu tun. Es ist höchstens ein Beispiel für schlechtes Design.

    zeusosc schrieb:

    Diskutieren wir doch mal gemeinsam die C++ Cast types

    const_cast const Ist nur für den zu kompilierenden kontext
    (strucktur konsistenz und lebenzeitprüfung zur kompilierzeit) und nicht für
    die ausführung des Sources relevant. (Einfach mal assembly anschauen)
    D.h. verwendet man ein const_cast so hat man einen struckturellen fehler in der
    Deklaration oder Definition.

    Wie Du zu dieser Schlussfolgerung kommst ist mir nicht klar.

    zeusosc schrieb:

    dynamic_cast Weg damit,wozu gibt es polymorphie,...

    dynamic_cast ist ein Werkzeug. Wenn Du es brauchst, benutze es. Wenn nicht, dann nicht. Ich stimme Dir zu, dass es in einigen Fällen missbraucht wird. Aber das gilt eigentlich für alles andere auch.

    zeusosc schrieb:

    reinterpret_cast
    A) Wozu gibt es Casting member Operatoren
    und 😎 (MSDN) The reinterpret_cast allows the pointer to be treated as an
    integral type. The result is then bit-shifted and XORed with itself to produce
    a unique index (unique to a high degree of probability). The index is then
    truncated by a standard C-style cast to the return type of the function.

    Dein Punkt A ergibt keinen Sinn, Punkt B sieht aus wie ein aus dem Zusammenhang gerissenes Zitat.

    zeusosc schrieb:

    static_cast
    (MSDN) Consequently, static_cast can do the inverse of implicit conversions, in
    which case the results are undefined. It is left to the programmer to verify
    that the results of a static_cast conversion are safe.

    This behavior also applies to types other than class types. For instance,
    static_cast can be used to convert from an int to a char. However, the
    resulting char may not have enough bits to hold the entire int value. Again, it
    is left to the programmer to verify that the results of a static_cast
    conversion are safe.

    -- So, und was ist der unterschied zum C_Cast ???

    Das wurde doch schon mehrfach erklärt. Es beschränt sich nicht nur auf Syntax-Highlighting.

    Nochmal:
    Ein C-style Cast ist je nach Kontext entweder ein dynamic_cast, static_cast, const_cast, reinterpret_cast oder eine Kombination davon. Wenn Du eine bestimmte Operation wünscht, dann hast Du mit einem C++-style Cast die Gelegenheit genau zu sagen, was Du willst. Damit kannst Du Fehler schon zur Compile-Zeit ausschließen. Zeige mir ein Beispiel wo Du ein C-style Cast für angebracht hältst und ich sage Dir, welchen Cast Du eigentlich damit machen wolltest, und wie Du das explizit mit einem C++-style Cast ausdrücken kannst...



  • Jo krümmelkacker, (cooler name 😃 )

    Mahlzeit erstmal....
    Also, die geposteten Sources sind aus dem Link und nicht von mir,
    welche die falsche handhabung von casts und insbesondere von C++ Style Casts
    verdeutlichen sollen!

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"
    (Ich habe nicht gesagt: macht das alle so, sonst gibt auf die nuss 😉 )

    Meine Argumentation basiert darauf, dass 50% der C++ Style Casts unnütz,
    und die anderen beiden so oder so auf C_Casts (oder Casting memberfkt's )
    zurück zu führen sind.

    Gehen wir mal auf den direkten vergleich von C_Cast und C++ Cast aus dem link ein:

    The old-style casts continue to be legal, but the new forms are preferable.
    First, they’re much easier to identify in code (both for humans
    and for tools like grep), thus simplifying the process of finding places
    in the code where the type system is being subverted. Second, the
    more narrowly specified purpose of each cast makes it possible for
    compilers to diagnose usage errors.

    A) Wenn ich nicht erkenne, wo das explicite typensystem unterlaufen wird, ist:
    I) Der Source schlecht dokumentiert
    II) Der Source unübersichtlich gestaltet
    III) Die Schnittstelle nicht ausreichend definiert

    😎 Wenn ich mich darauf verlasse das erst der Kompiler mir sagen muss das ein möglicher Semantischer Fehler vorliegt:
    I) Ist keine ausreichende Prüfung des eigenen Source im zuge der Schnittstellen tests garantiert
    II) Ist dem programmierer nicht klar wie er das Object eigentlich behandeln will
    (Was auf ein Konzeptionellen Fehler im PAP zurück zu führen ist..)

    So, nochmal zu den Casting types:

    const_cast
    Wenn eine Schnittstelle einen Parameter als Const deklariert, ist diese
    auch als const zu verwenden! "Don't define, what ya don't need!"

    Wenn das const weg gecasted wird um eine member fkt zu callen, die nicht
    für einen const garantiert, oder einen member zu verändern, so ist DEFENITIV
    die Schnittstelle (member func) falsch definiert!

    Man stelle sich doch nur mal vor, in einem multithreaded-app Project verlässt sich ein Programmierer auf diese const spec, aber in wirklichkeit wird
    das ding einfach weggecasted um einen member zu verändern...
    ..und schwup hat man einen laufzeitfehler 0x00....05 Access Error

    Also nochmal "Don't define, what ya don't need". Wird ein const
    in der Definition garantiert, so MUSS sich der programmierer daran halten!

    Fazit: const_cast ist unnötig, da es die specs umgeht..!

    dynamic_cast Der einzige sinnvolle einsatz wäre, den this ptr des
    eigenen objectes nicht manuell adjustieren zu müssen.
    Da es aber auch ohne geht (siehe geposteten Source^^) erübrigt sich die frage
    ob man das braucht.

    reinterpret_cast
    Zu der MSDN lektüre, ja ein bissl aus dem kontext gerissen, aber gleich alles
    zu posten muss ja net sein 🙂
    Ein reinterpret_cast macht das gleiche wie, kopiere speicherbereich a,
    zu einem (prinzipiell) im stack initialiserten typen b.
    Also nichts weiter als ein grobes memcpy_s(&b,sizeof(Typename T),a,sizeof(Typename T)).
    Und ein reinterpret_cast gewähleistet mir auch nicht das zur Laufzeit der addressierte
    speicherbereich von a valide ist und in der richtigen größe vorhanden ist.

    Zu den Casting Member Operatoren:

    //nur ein schnelles beispiel, für non-void ptrs die zu reinterpretieren sind
    class Test
    {
    //...
    public:
    operator double() { return 1.0f;};
    operator double*() { return new double(1.9f);};
    }
    

    static_cast
    Verhält sich exakt wie ein C_Cast.

    Also nochmal zusammenfassend:
    Verwendet man const_cast hat man einen designfehler,
    dynamic_cast ist genauso sinnlos,
    reinterpret_cast hilft mir zur laufzeit bei void ptrs überhaupt nicht,
    ansonsten gibt es laufzeit ausführbare casting memberfkt's (operatoren)
    static_cast verhält sich wie ein C_Cast, laufzeit sicherheit ist auch nicht gewährleistet...

    Die frage die sich mir dann stellt:
    Wo ist der Mehrwert?

    Bei einem C_Style Cast oder einer direkten zuweisung mit implizitem casting,
    wird gecheckt ob ein passender konvertierungsmechanismus vorhanden ist.

    Ich würde auch nicht sagen, dass C_Casts eine Holzhammermethode ist,
    sondern C_Casts sind explicite anweisungen an den kompiler,
    wie er ein datensegment zu behandeln hat.

    So zeit zum Krümmel Kacken 😃

    Statements requested ....
    ---------------------------------------
    P.S.: Ziel der diskussion ist die Casting methoden auseinander zu nehmen und zu
    Erörtern... Nicht Euch meine meinung aufzustempeln! ⚠



  • zeusosc schrieb:

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"

    Es reicht Assembler zu benützen.
    Das macht es noch lange keine gute Idee.

    Meine Argumentation basiert darauf, dass 50% der C++ Style Casts unnütz,
    und die anderen beiden so oder so auf C_Casts (oder Casting memberfkt's )
    zurück zu führen sind.

    Und genau das ist der Schwachsinn den wir hier bekriteln.
    Die C++ Casts sind deshalb so toll, weil sie precise sind. Ein static_cast sagt: hier passiert nichts unanständiges (reinterpret) und es wird kein const weggenommen.

    Ein C Casts sag: ich mach aus A ein B, komme was wolle. Auch wenn A und B nichts miteinander zu tun haben, ich quetsch dass da zusammen und ignoriere const correctness dabei.

    Ein reintrepret_cast ist fast wie ein C cast, mit dem unterschied dass er auf const correctness achtet. dh wenn ich einen reintrepret_cast sehe, dann weiss ich sofort: Achtung, da wird an den typen rumgemurkst - aber wenigstens kann ich mich auf const correctness verlassen.

    dynamic_cast gibts in C sowieso nicht. Und const_cast ist super um zu sagen: hier tue ich nur das const wegnehmen. Das ist sofort eine rote Flagge: Warum will ich das? Aber ich weiss sofort was hier passiert.

    A) Wenn ich nicht erkenne, wo das explicite typensystem unterlaufen wird, ist:
    I) Der Source schlecht dokumentiert
    II) Der Source unübersichtlich gestaltet
    III) Die Schnittstelle nicht ausreichend definiert

    Äh, schonmal mit großen Projekten gearbeitet? Das mag in der Theorie ja gut klingen, dass du durch guten Code und gute Doku immer auch einen C Casts auf genau einen Verwendungszweck reduzieren kannst - in der Praxis ist das aber nicht möglich.

    😎 Wenn ich mich darauf verlasse das erst der Kompiler mir sagen muss das ein möglicher Semantischer Fehler vorliegt:

    Du willst das IMMER haben. Der Compiler soll dir IMMER sagen wenn du wo einen semantischen Fehler hast.

    I) Ist keine ausreichende Prüfung des eigenen Source im zuge der Schnittstellen tests garantiert
    II) Ist dem programmierer nicht klar wie er das Object eigentlich behandeln will
    (Was auf ein Konzeptionellen Fehler im PAP zurück zu führen ist..)

    Das ist wieder nur reine Theorie. In der Theorie ist jeder Source Code perfekt. In der Praxis aber ist es ungemein praktisch wenn der Compiler dabei hilft.

    Der Rest des Postings von dir war nur blödsinn. Sorry. const_cast wird zB gebraucht um bei funktionen die handles auf interne Daten liefern (das objekt also nicht ändern) keine code duplizierung für const und nicht const zu haben. dynamic_cast kann verwendet werden um den Typ eines Objektes herauszufinden oder zB cross casts zu machen.

    Bedenke, dass ein c casts all das macht, was du in C++ bei den casts für unnötig befindest. Wenn du zB sagst const und reintrepret sind unnötig: dann bedenke dass ein C cast genau das aber macht. Ein C casts ist eine const-static-reintrepret Mischung die ALLES erlaubt.

    Deshalb: nur static_cast verwenden für die normalen Casts und man kann garkeine Fehler mehr machen. Bedenke, dass in der Programmierung es immer wichtig ist diese automatischen Kontrollen zu haben. In der Theorie sind wir alle vielleicht unfehlbar, in der Praxis passieren jedem von uns täglich mehrere Fehler. Wenn der Compiler mir den Fehler sofort anzeigt, spare ich massig Zeit.

    PS:

    Bei einem C_Style Cast oder einer direkten zuweisung mit implizitem casting,
    wird gecheckt ob ein passender konvertierungsmechanismus vorhanden ist.

    Nein. Ein C Cast nimmt den Wert und steckt ihn in den Typen rein. Egal was. Egal wer. Egal wo. Du willst aus einem Vogel ein Auto machen? -> C Cast kann das.



  • Shade Of Mine schrieb:

    zeusosc schrieb:

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"

    Es reicht Assembler zu benützen.

    haha,.. ja 😃

    Shade Of Mine schrieb:

    PS:

    Bei einem C_Style Cast oder einer direkten zuweisung mit implizitem casting,
    wird gecheckt ob ein passender konvertierungsmechanismus vorhanden ist.

    Nein. Ein C Cast nimmt den Wert und steckt ihn in den Typen rein. Egal was.
    Egal wer. Egal wo. Du willst aus einem Vogel ein Auto machen? -> C Cast kann das.

    Nö,.. das ist schlichtweg falsch. Ein C_Cast unter einem C++ Compiler prüft ob
    dementsprechende operanden (Konvertierungsmechanismen) vorhanden sind
    und ersetzt diese dann:

    Test a;
    00297B7B  lea         ecx,[a] 
    00297B81  call        Test::Test (2986F0h) 
    Test b(a);
    00297B86  lea         eax,[a] 
    00297B8C  push        eax  
    00297B8D  lea         ecx,[b] 
    00297B93  call        Test::Test (298710h) 
    double d=(double)b;
    00297B98  lea         ecx,[b] 
    00297B9E  call        Test::operator double (298760h) 
    00297BA3  fstp        qword ptr [d]
    

    Shade Of Mine schrieb:

    Ein reintrepret_cast ist fast wie ein C cast, mit dem unterschied dass er auf
    const correctness achtet. dh wenn ich einen reintrepret_cast sehe, dann weiss
    ich sofort: Achtung, da wird an den typen rumgemurkst - aber wenigstens kann
    ich mich auf const correctness verlassen.

    int *k=0;
    const int j=5;
    k=reinterpret_cast<int*>(&j); // ERROR: C2440 cannot convert from 'const int *' to 'int *'
    //1>        Conversion loses qualifiers
    *k=3;
    

    Richtig.. kann man,...
    Braucht man es wenn die schnittstelle definiert das es ein const sein muss?

    Shade Of Mine schrieb:

    Und const_cast ist super um zu sagen: hier tue ich nur das const wegnehmen. Das ist sofort eine rote Flagge: Warum will ich das? Aber ich weiss sofort was hier passiert.

    A) Wenn ich nicht erkenne, wo das explicite typensystem unterlaufen wird, ist:
    I) Der Source schlecht dokumentiert
    II) Der Source unübersichtlich gestaltet
    III) Die Schnittstelle nicht ausreichend definiert

    Äh, schonmal mit großen Projekten gearbeitet? Das mag in der Theorie ja gut
    klingen, dass du durch guten Code und gute Doku immer auch einen C Casts auf
    genau einen Verwendungszweck reduzieren kannst - in der Praxis ist das aber
    nicht möglich.

    Und ob das möglich ist,... nehmen wir ein beispiel:

    class Test
    {
    private:
    bool a;
    
    public:
    bool Methode_a(void)
    { return this->a; }
    
    Test & operator=(const Test &b)
    {
    		if(this==&b) return *this;
    
    		this->a=b.Methode_a(); //error C2662: 'Test::Methode_a' : cannot convert 'this' pointer from 'const Test' to 'Test &'
    1>        Conversion loses qualifiers
    
    		return *this;
    };
    

    Füge ich hingegen eine const -Qualifizierte überladung durch:

    bool Methode_a(void) const
    {
     return this->a;
    }
    

    Wird ohne Murksen kompiliert. Und das auch mit grund.
    Setzt man das in verbindung mit den casting operatoren,
    schon hat man ein const safe type (C Style) casting
    ,....

    Nehmen wir noch ein anderes Beispiel:

    Test& Eine_Beispiel_Function( const void * foo)
    {
     Test * a = ( const Test*) foo; // error: cannot convert from 'const Test *' to 'Test *'
     a=(Test*)foo; //kein error <- einzige variante die einen fehler verursachen könnte, wenn man in der behandlung nicht aufpasst
     a=reinterpret_cast<const Test*>(foo); // error: cannot convert from 'const Test *' to 'Test *'
     a=reinterpret_cast<Test*>(foo); //error:  cannot convert from 'const void *' to 'Test *'
     const Test *b=(Test*) foo; //kein error, und auch nicht falsch
     b= reinterpret_cast<Test*>(foo); //error: cannot convert from 'const void *' to 'Test *'
     b=(const Test*)foo;//kein error, und auch nicht falsch
     b=reinterpret_cast<const Test*>(foo);//kein error und auch net falsch
    
    return *a;
    };
    

    D.h. ist eine const Eigenschaft für das element über die deklaration
    gegeben, so muss ich die natürlich für den gecasteten typen übernehmen..

    const Test * b= (Test*) foo;
    

    ist für die behandlung mehr als ausreichend, wenn ein cast
    auf ein element das const -attribut erforderlich ist.

    Ich kenne (also) kein Beispiel das mir die Erforderniss von
    const_cast und reinterpret_cast klar macht (unter berücksichtigung benannter typenbehandlung)!

    Shade Of Mine schrieb:

    Bedenke, dass ein c casts all das macht, was du in C++ bei den casts für
    unnötig befindest. Wenn du zB sagst const und reintrepret sind unnötig: dann
    bedenke dass ein C cast genau das aber macht. Ein C casts ist eine const-static-
    reintrepret Mischung die ALLES erlaubt.

    Unter einem C++ Kompiler macht ein C_Cast das eben nicht.
    Dieser wird wie ein konvertierungs-operator behandelt (siehe gaaanz oben in diesem Post)
    welche ausreichend deklariert und definiert werden müssen. 💡

    Verzichtet man hingegen darauf, ist es klar das die typenbehandlung ausgelagert werden muss.

    Grüüüüüüße



  • @zeusosc:
    C++ Style Casts sind genau so nützlich oder unnütz wie const , dass Integers nicht automatisch zu Enum Typen konvertiert werden dürfen, dass void-Pointer nicht automatisch in typisierte Zeiger konvertiert werden dürfen und 100 andere Sachen in C++, die nur dazu da sind Fehler zu vermeiden.

    Wenn du lieber etwas schreibst wo der Compiler viel weniger Chancen hat von dir unbeabsichtigte Fehler zu finden: fein. Mach es so. Aber bewirb es bloss nicht hier, oder behaupte dass C++ Style Casts deswegen unnötig wären, weil du nicht verstanden hast wozu sie gut sind (oder sie einfach trotzdem nicht verwenden willst).

    Unter einem C++ Kompiler macht ein C_Cast das eben nicht.
    Dieser wird wie ein konvertierungs-operator behandelt (siehe gaaanz oben in diesem Post)
    welche ausreichend deklariert und definiert werden müssen.

    Ein C Style Cast macht unter C++ so ziemlich alles, inklusive const_ und reinterpret_cast. Steht auch so im Standard.



  • Gerade dein Beispiel "Eine_Beispiel_Function widerlegt" doch das, was du uns nahebringen willst: Die Kernaussage ist "be precise", und indem du eine Funktion mit einem void Pointer hast, bei der der Pointer auf eine Klasse zeigt ist der Ansatz doch schon völlig falsch. Entweder benutzt man statischen Polymorphismus durch templates oder Laufzeitpolymorphismus durch Vererbung.
    Deine Funktion erlaubt es, Birnenbäume zu übergeben und erwartet Fensterhandles, robuste Programmierung ist etwas anderes.
    Casts werden dazu benutzt, um Brücken zu schlagen, wobei dir bei den C++ casts der Compiler klar sagt, welche Brücken erlaubt sind und welche nicht, d.h. er erkennt bereits zur Compile time mögliche Fehler und garantiert Typsicherheit. Bei C casts ist das eben nicht so, das ist wie Hochseilakrobatik ohne Netz. Geht meistens gut, muss aber nicht, und wenn nicht, dann fatal. Allein diese Tatsache macht diese Diskussion hinfällig, wenn jemand so programmieren möchte kann er das gerne tun, aber die Behauptung, das sei besserer Stil und schneller lässt mich aus der Diskussion aussteigen. Über Nonsens diskutiert man nicht, Punkt.



  • zeusosc schrieb:

    Nö,.. das ist schlichtweg falsch. Ein C_Cast unter einem C++ Compiler prüft ob
    dementsprechende operanden (Konvertierungsmechanismen) vorhanden sind
    und ersetzt diese dann:

    class A {};
    class B {};
    
    void f(B const& b) {}
    
    int main() {
       A a;
       f((B const&)a);  //geht
       //f(static_cast<B const&>(a)); //geht nicht
    }
    

    Der Rest deines Posts ist etwa genauso wahr wie diese Aussage.
    Deshalb beende ich es für mich.

    Nur weil du ein Beispiel bringst wo const cast nicht notwendig ist, heisst es nicht dass const cast NIE notwendig ist. btw c casts sind immer auch const casts...

    Ich kenne (also) kein Beispiel das mir die Erforderniss von
    const_cast und reinterpret_cast klar macht (unter berücksichtigung benannter typenbehandlung)!

    const cast Beispiel:

    class A {
    private:
       int i;
    
    public:
       int getI() const { return const_cast<A*>(this)->getI(); }
       int& getI() { return i; }
    };
    

    Stell dir vor getI sei komplex.

    Beispiel für reintrepret_cast:

    int buffer;
       char* bytes;
       bytes = reinterpret_cast<char*>(&buffer);
    

    Du willst zB ein Sammlung von ints als einzelne Bytes behandeln bzw. einen Bytestrom als eine Ansammlung von ints.

    Es gibt millionen Fälle wo dieser oder jener Cast praktisch ist. Bedenke bitte: der C Cast macht immer reintrepret+const Cast.



  • zeusosc schrieb:

    Nö,.. das ist schlichtweg falsch. Ein C_Cast unter einem C++ Compiler prüft ob
    dementsprechende operanden (Konvertierungsmechanismen) vorhanden sind
    und ersetzt diese dann

    Ein C-Cast versucht die Typen irgendwie umzubiegen. Sofern das geht, wird es getan. Darunter fallen viele unerwünschte Fälle.

    Und was der Assemblercode an dieser Stelle soll, erschliesst sich mir nicht. Aber wie schon im anderen Thread ist er ein schlechtes Argument.

    zeusosc schrieb:

    Und ob das möglich ist,... nehmen wir ein beispiel:

    bool Methode_a(void)
    { return this->a; }
    
    Test & operator=(const Test &b)
    {
    		if(this==&b) return *this;
    
    		this->a=b.Methode_a(); //error C2662: 'Test::Methode_a' : cannot convert 'this' pointer from 'const Test' to 'Test &'
    1>        Conversion loses qualifiers
    
    		return *this;
    };
    

    Nur schade, dass hier nirgends ein C-Cast im Spiel ist...

    zeusosc schrieb:

    Unter einem C++ Kompiler macht ein C_Cast das eben nicht.

    Natürlich ist ein C-Cast die Kombination von static_cast , reinterpret_cast und const_cast und je nachdem wird auch mehreres auf einmal angewandt. Und wie du auf Konvertierungsoperatoren (das sind die Memberfunktionen) kommst, weiss ich auch nicht.



  • Au,.. so viele schöne kontras 🙂

    Nexus schrieb:

    Und was der Assemblercode an dieser Stelle soll, erschliesst sich mir nicht.
    Aber wie schon im anderen Thread ist er ein schlechtes Argument.

    ..um präzise zu sein, ist das kein Argument sondern ein Beweissmitteln zur untermauerung meiner Argumentation...

    Nexus schrieb:

    Und wie du auf Konvertierungsoperatoren (das sind die Memberfunktionen) kommst, weiss ich auch nicht.

    Ok, mal gucken ob ich Dir es so näher bringen kann... (Schau es Dir aber auch an)

    Um die mechanismen zu verstehen, die man benutzt, muss man sich auch anschauen
    wie diese umgesetzt werden. Das mache ich jetzt (nochmal... ich weiß jaja 🙂 )

    Als C -Style Cast bezeichne ich:

    Object_A objA;
    Object_B B = (Object_B) objA;
    

    Im konkreten Fall bei einem Casting eines Objectes zu einem Basistypen:

    Test a;
    012A7B7B  lea         ecx,[a] 
    012A7B81  call        Test::Test (12A86F0h) 
    
    double d=(double)a;
    012A7B86  lea         ecx,[a] 
    012A7B8C  call        Test::operator double (12A8710h) 
    012A7B91  fstp        qword ptr [d] 
    
    double*e=(double*)a;
    012A7B97  lea         ecx,[a] 
    012A7B9D  call        Test::operator double * (12A8730h) 
    012A7BA2  mov         dword ptr [e],eax
    

    Für das Object:

    class Test
    {
    private:
    	double d;
    public:
    	Test(){};
    	operator double() { return this->d;};
      	operator double*() { return &this->d;};
    };
    

    Wie man in der assembly sehen kann, wird der C_Cast auf die spezifischen
    casting operator umgeleitet.

    Das Argument bezog sich darauf, das ein C_Cast in der übersetzung keine
    "Umbiegung" ist, sondern explicit nach einer definierten Konvertierung gesucht und ersetzt wird.
    Das ist bei der deklaration von dem Casting operator "operator double()" der
    Fall". Das gleiche gilt für einen RVALUE type void*, sofern dieser implementiert ist.

    Die Folgerung dieses Beispiels ist:
    Wenn man ein Object casten will, kann man das laufzeitkonvertierungsmechanismen
    überlassen, die auch auf korrektheit des typs prüfen können. Und das mit
    C Style Casts, die ja wie oben gezeigt, wenn implementiert, in Casting Methoden
    umegeleitet werden.

    Frage: Ist diese Folgerung falsch?

    Nexus schrieb:

    Nur schade, dass hier nirgends ein C-Cast im Spiel ist...

    Bezog sich eher auf die (nicht) notwendigkeit von const_cast,....
    das kam vlt. nicht so rüber...

    Shade Of Mine schrieb:

    class A {
    private:
       int i;
    
    public:
    	A() { i=0;};
    	A(const A& a) { this->i=a.getI(); };
       int getI() const { return const_cast<A*>(this)->getI(); }
       int& getI() { return i; }
    };
    

    Ein schönes Beispiel.
    Da aber getI() nicht komplex ist reicht auch:

    int &getI() { return i;}
    int const &getI() const { return i;}
    

    Hast Du vlt. noch ein anders Beispiel?

    DocShoe schrieb:

    und indem du eine Funktion mit einem void Pointer hast, bei der der Pointer auf
    eine Klasse zeigt ist der Ansatz doch schon völlig falsch. Entweder benutzt
    man statischen Polymorphismus durch templates oder Laufzeitpolymorphismus durch Vererbung.

    Ja, da hast du recht.
    Dabei bezog ich mich aber auf Beispiele für den Verwendungszweck, welche in
    referenzen von reinterpret_cast vorliegen:
    http://msdn.microsoft.com/en-us/library/e0w9f63b(VS.80).aspx
    Das reicht aber um den worst case des Anwendungsfalls zu verdeutlichen.

    hustbear schrieb:

    Aber bewirb es bloss nicht hier, oder behaupte dass C++ Style Casts deswegen
    unnötig wären, weil du nicht verstanden hast wozu sie gut sind (oder sie
    einfach trotzdem nicht verwenden willst).

    Mensch hustbear, ich habe doch schon in einem vorherigen Post geschrieben was
    meine intension ist. Aber Dir zu liebe nochmal:

    ich schrieb:

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"
    (Ich habe nicht gesagt: macht das alle so, sonst gibt auf die nuss 😉 )
    ...
    P.S.: Ziel der diskussion ist die Casting methoden auseinander zu nehmen und zu
    Erörtern... Nicht Euch meine meinung aufzustempeln! ⚠

    Ich habe nicht gesagt das ein C_Cast kein reinterpret_cast, kein static_cast, kein const_cast und auch kein dynamic_cast macht.

    Das was ich sage ist: Wenn man weiß, und testet, wie der (oder ein) C_Cast
    sich auf das datensegment von einem Basistyp oder anderes Object (oder ptr) auswirkt,
    sowie methoden und/oder funktionen implementiert die eine richtige Behandlung und Prüfung zur Kompilierzeit und zur Laufzeit sicherstellen, dann sind
    (oder sollten) alle relevanten qualitätsmerkmale (á la SQuaRE) erfüllt sein.

    Es ist natürlich richtig das jede meldung im Compiler das Leben des Programmierers vereinfacht und gerade unter Termindruck flüchtigkeitsfehler
    ausschließen will.

    Wenn ich vergessen habe auf irgendein statement von euch genauer einzugehen, sagt nochmal bÖscheid.

    grüüßli 😃



  • Machen denn hier der C-Style cast und der static_cast auch das gleiche?

    class A;
    class B;
    
    B& toB1( A& aA )
    {
            return (B&)aA;
    }
    
    B& toB2( A& aA )
    {
            return static_cast<B&>(aA);
    }
    


  • zeusosc schrieb:

    Ok, mal gucken ob ich Dir es so näher bringen kann... (Schau es Dir aber auch an)

    Du solltest bedenken dass Nexus von C++ ein paar Ecken mehr versteht als du bevor du solche Formulierungen verwendest...

    Wenn man ein Object casten will, kann man das laufzeitkonvertierungsmechanismen
    überlassen, die auch auf korrektheit des typs prüfen können. Und das mit
    C Style Casts, die ja wie oben gezeigt, wenn implementiert, in Casting Methoden
    umegeleitet werden.

    Frage: Ist diese Folgerung falsch?

    Ja. Sie ist komplett falsch.
    Natürlich findest du Situationen wo C Casts genau das richtige tun. Es ist ja nicht so als wären sie kaputt und würden nicht funktionieren. Aber das geht eben komplett am Thema vorbei. Schau dir mein Codebeispiel mal an (und vergiss den Assembler Code der sagt nichts aus):

    class A {}; 
    class B {}; 
    
    void f(B const& b) {} 
    
    int main() { 
       A a; 
       f((B const&)a);  //geht 
       //f(static_cast<B const&>(a)); //geht nicht 
    }
    

    Ein simpler, einfacher Gegenbeweis.
    C Casts machen böse Sachen. Die Konvertierung von a nach B ist illegal. C Casts machen sie dennoch. Das ist Gefährlich. Deshalb: c++ casts verwenden.

    Bezog sich eher auf die (nicht) notwendigkeit von const_cast,....

    Du kannst nicht mit einem Beispiel wo X nicht notwendig ist Beweisen, dass X nie notwendig ist. So funktioniert das nicht.

    Ein schönes Beispiel.
    Da aber getI() nicht komplex ist reicht auch:

    int &getI() { return i;}
    int const &getI() const { return i;}
    

    Stell dir einfach vor getI sei komplex. Man kann immer etwas drum herum bauen - klar. Aber das hier ist ein Fall wo man idR mit const_cast am besten fährt.

    Hast Du vlt. noch ein anders Beispiel?

    Klar. Wenn man eine API verwenden muss die nicht const-correct ist.

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"

    Wie schon gesagt: nur weil man etwas machen kann, ist es noch lange keine gute Idee. C Casts sind eine furchtbar dumm Idee. Aber klar, ich kann auch freihändig mit dem Auto auf der Autobahn fahren. Klar geht das. Aber eine gute Idee ist etwas anderes.

    Das was ich sage ist: Wenn man weiß, und testet, wie der (oder ein) C_Cast
    sich auf das datensegment von einem Basistyp oder anderes Object (oder ptr) auswirkt,
    sowie methoden und/oder funktionen implementiert die eine richtige Behandlung und Prüfung zur Kompilierzeit und zur Laufzeit sicherstellen, dann sind
    (oder sollten) alle relevanten qualitätsmerkmale (á la SQuaRE) erfüllt sein.

    Du erreichst mit enromen mehr Aufwand ein fast so gutes Ergebnis wie mit C++ Casts. Ja.


  • Mod

    zeusosc schrieb:

    ...

    Wie man in der assembly sehen kann, wird der C_Cast auf die spezifischen
    casting operator umgeleitet.

    Das Argument bezog sich darauf, das ein C_Cast in der übersetzung keine
    "Umbiegung" ist, sondern explicit nach einer definierten Konvertierung gesucht und ersetzt wird.

    Worauf willst du eigentlich hinaus? Es ist schon klar, dass genau definiert ist, was der C-Cast macht. Es geht darum, dass man es ihm nicht unbedingt ansieht, weil er alles machen könnte. Einmal nicht aufgepasst (egal ob an Stelle des Casts oder irgendwo weit vorher) -> kein Compilerfehler, aber dafür semantischer Fehler im Programm. Sehr schwer zu finden. Besonders da man die C-Casts noch nicht einmal gut suchen kann.

    Bezog sich eher auf die (nicht) notwendigkeit von const_cast,....
    das kam vlt. nicht so rüber...

    Schön. const_cast ist auch nicht nötig und wenn man es doch braucht, dann ist das ein Warnsignal, dass etwas falsch ist. Wieso wolltest du nochmal einen Cast benutzen, der const_cast mit beinhaltet und bei dem man nicht einmal merkt, dass man ihn benutzt?

    Ja, da hast du recht.
    Dabei bezog ich mich aber auf Beispiele für den Verwendungszweck, welche in
    referenzen von reinterpret_cast vorliegen:
    http://msdn.microsoft.com/en-us/library/e0w9f63b(VS.80).aspx
    Das reicht aber um den worst case des Anwendungsfalls zu verdeutlichen.

    Schön. reinterpret_cast ist auch nicht nötig und wenn man es doch braucht, dann ist das ein Warnsignal, dass etwas falsch ist. Wieso wolltest du nochmal einen Cast benutzen, der reinterpret_cast mit beinhaltet und bei dem man nicht einmal merkt, dass man ihn benutzt?

    "Es reicht C_Cast zu benützen!"

    Es gibt viele Sachen die ausreichend sind, aber deshalb ist es noch lange nicht gut, so zu handeln.

    Das was ich sage ist: Wenn man weiß, und testet, wie der (oder ein) C_Cast
    sich auf das datensegment von einem Basistyp oder anderes Object (oder ptr) auswirkt,
    sowie methoden und/oder funktionen implementiert die eine richtige Behandlung und Prüfung zur Kompilierzeit und zur Laufzeit sicherstellen, dann sind
    (oder sollten) alle relevanten qualitätsmerkmale (á la SQuaRE) erfüllt sein.

    Schön. Also anstatt eine semantische Prüfung durch den Compiler automatisiert vorzunehmen, soll ich jetzt umfangreiche Tests machen. Da habe ich ja echt viel gewonnen 🙄 .

    Es ist natürlich richtig das jede meldung im Compiler das Leben des Programmierers vereinfacht und gerade unter Termindruck flüchtigkeitsfehler
    ausschließen will.

    Warum willst du sie dann umgehen?



  • zeusosc schrieb:

    hustbear schrieb:

    Aber bewirb es bloss nicht hier, oder behaupte dass C++ Style Casts deswegen
    unnötig wären, weil du nicht verstanden hast wozu sie gut sind (oder sie
    einfach trotzdem nicht verwenden willst).

    Mensch hustbear, ich habe doch schon in einem vorherigen Post geschrieben was
    meine intension ist. Aber Dir zu liebe nochmal:

    ich schrieb:

    Das Ziel meiner Argumentation ist, die Aussage verständlich zu machen:
    "Es reicht C_Cast zu benützen!"
    (Ich habe nicht gesagt: macht das alle so, sonst gibt auf die nuss 😉 )
    ...
    P.S.: Ziel der diskussion ist die Casting methoden auseinander zu nehmen und zu
    Erörtern... Nicht Euch meine meinung aufzustempeln! ⚠

    Ich habe nicht gesagt das ein C_Cast kein reinterpret_cast, kein static_cast, kein const_cast und auch kein dynamic_cast macht.

    Das was ich sage ist: Wenn man weiß, und testet, wie der (oder ein) C_Cast
    sich auf das datensegment von einem Basistyp oder anderes Object (oder ptr) auswirkt,
    (...)

    Mal abgesehen davon dass du eine sehr eigenwillige (und IMO total falsche) Interpretation von "Datensegment" hast...

    Ja, wenn man weiss was man tut kann man auf C++ Style Casts verzichten, solange man keinen dynamic_cast braucht.
    Nur wieso sollte man das wollen?
    Wenn man weiss was man tut kann man wie gesagt auf viel verzichten. Man kann überall das const weglassen und statt T const& überall T& rumreichen. Führt zu toll unwartbarem Code.
    Genauso führt IMO die Verwendung von C-Style Casts zu toll unwartbarem Code.

    Dass es geht wurde jetzt glaube ich schon oft genug festgestellt. Also worum geht es dir jetzt noch, abgesehen von dieser (IMO ziemlich wertlosen) Feststellung?



  • @Shade:

    Ich wollte niemanden ans Bein pinkeln. Sollte es so rübergekommen sein, dann
    entschuldige ich mich gerne. Ich hatte bei der Aussage zu Nexus nur den eindruck
    er hätte mein Post zu rasch überflogen... Daher entschuldige Nexus...

    @Shade + SeppJ:
    Eure beiden aussagen (mal zusammengefasst)
    "Mit mehr aufwand für ein ordentliches C_Cast erreicht man das gleiche wie
    es die C++ Style Casts schon (viel einfacher) machen!" finde ich gut und bringt
    die sache glaube ich auch auf exakt den Punkt. 🕶

    Blöd ist: ich habe jetzt summa sumarum keine Gegenargumente mehr ...

    Daher thx at all 👍
    ---------------------------------------
    Edit:

    hustbear schrieb:

    Dass es geht wurde jetzt glaube ich schon oft genug festgestellt. Also worum geht es dir jetzt noch, abgesehen von dieser (IMO ziemlich wertlosen) Feststellung?

    Das wars eigentlich schon,.. trozdem danke 🙂



  • Siiiiieg 😉


Anmelden zum Antworten