casten
-
Hallo,
ich habe eine allgemeine Frage zum Thema casten. In meinem Buch (C++ für Spieleprogrammierer) kam das in Kapitel 2 vor (bin mittlerweile ungf. in der Mitte des Buches). Nun ist aber das Problem, dass ich irgendwie diesen Text im Buch über Casten nicht kapiere. Ich weiß wie man das schreibt
static_cast<int> (number1-number2)zB.Aber warum ist casten gut?!
Wann würde man soetwas in einem Programm gebrauchen?Danke im Voraus für Aufklärungen

-
Um dem Compiler klar zu machen, dass man wirklich einen Typkonvertierung will:
float f = 10.5; int i = f; // Warnung bzw. Fehler da Nachkommastellen verloren gehen
-
oder char in int:
char a = 'a'; int i = static_cast<int> (a); //i=97 (dezimal) (hexadez. = 61)
-
Ein gutes Beispiel sind C-Funktionen, die Userdaten als void-pointer zulassen, in z.Bsp. Callbacks:
class Foo { void bar() { c_lib_method(my_callback, this); } void log(const char* msg) { std::cout << msg << std::endl; } }; void my_callback(int a, void* userdata) { Foo* f = dynamic_cast<Foo*>(userdata); f->log("blabla"); }Die Funktion c_lib_method würde jetzt jedesmal wenn sie my_callback aufruft den this-Zeiger von Foo mit übergeben und man kann auf diese Klasse zugreifen.
Nur ein weiteres Szenario. Mit C++ sollte man solche Callbacks natürlich nicht mehr erzeugen, da kann man Basisklassen etc verwenden für.
-
Scorcher24 schrieb:
class Foo { void bar() { c_lib_method(my_callback, this); } void log(const char* msg) { std::cout << msg << std::endl; } }; void my_callback(int a, void* userdata) { Foo* f = dynamic_cast<Foo*>(userdata); f->log("blabla"); }Einen dynamic_cast mit void* sollte der Compiler aber zurückweisen.
-
Stimmt, muss ein static_Cast sein. Naja war früh

-
Hi,
Da C/C++ eine explicite Typenkonvention nutzt, muss dem Compiler klar gemacht
werden, wie das Datensegment explecit zur Laufzeit behandelt werden soll.Bei ptrs auf Objecte oder Basistypen reichen also C-Casts des alten Stils.
(Es gibt eigentlich keinen vernünftigen grund dyn_casts<> oder static casts<>
den C_Casts vorzuziehen, ausser das diese in der IDE gehighlighted werden..
siehe http://www.aristeia.com/EC3E/3E_item27.pdf)grüße
-
zeusosc schrieb:
Es gibt eigentlich keinen vernünftigen grund dyn_casts<> oder static casts<>
den C_Casts vorzuziehen, ausser das diese in der IDE gehighlighted werden..
siehe http://www.aristeia.com/EC3E/3E_item27.pdfLies bitte deinen eigenen Link.
-
Habe ich doch

Prefer C++-style casts to old-style casts. They are easier to see, and
they are more specific about what they do.Das ist der einzige grund diese zu nutzen, und für mich kein vernünftiger da
mir das Kompilierverhalten bekannt ist.Ist doch genau was ich in meinen vorherigen post geschrieben habe oder nicht?
greetz
-
zeusosc schrieb:
Das ist der einzige grund diese zu nutzen, und für mich kein vernünftiger da
mir das Kompilierverhalten bekannt ist.Be precise
ist einer der wichtigsten Punkte beim Programmieren.Deshalb: c++ style casts vorziehen.
PS:
wenn du das anders siehst, dann lies den Link noch ein paar mal.
-
manni66 schrieb:
Scorcher24 schrieb:
class Foo { void bar() { c_lib_method(my_callback, this); } void log(const char* msg) { std::cout << msg << std::endl; } }; void my_callback(int a, void* userdata) { Foo* f = dynamic_cast<Foo*>(userdata); f->log("blabla"); }Einen dynamic_cast mit void* sollte der Compiler aber zurückweisen.
In dieser Richtung: ja.
In der anderen ist es lustigerweise erlaubt (also void* als Target).
Dann bekommt man einen Zeiger auf die "most derived class".
-
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_castWeil 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_castconst 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_castWeg 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_castconst 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_castWeg 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
constspec, aber in wirklichkeit wird
das ding einfach weggecasted um einen member zu verändern...
..und schwup hat man einen laufzeitfehler 0x00....05 Access ErrorAlso 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_castist unnötig, da es die specs umgeht..!dynamic_castDer 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 manconst_casthat man einen designfehler,
dynamic_castist genauso sinnlos,
reinterpret_casthilft mir zur laufzeit bei void ptrs überhaupt nicht,
ansonsten gibt es laufzeit ausführbare casting memberfkt's (operatoren)
static_castverhä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 einconst 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
constEigenschaft 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 dasconst-attribut erforderlich ist.Ich kenne (also) kein Beispiel das mir die Erforderniss von
const_castundreinterpret_castklar 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 wieconst, 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 dannEin 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_castundconst_castund 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],eaxFü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 vonreinterpret_castvorliegen:
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
