Ein const_cast
wird wie folgt aufgebaut
const_cast< TypVonObject_ohne_Const >( object )
Zurückgegeben wird das übergebene Objekt, der allerdings im Datentyp den const
-Qualifizierer verloren hat.
Ein Const-Cast ist eine legitimierte Notlösung. Gelegentlich stößt man auf alte Funktionen, die zwar noch benötigt werden, jedoch zu einer Zeit geschrieben wurden, als Const-Correctness für die meisten Entwickler noch ein Fremdwort war.
Hat man Beispielsweise eine Funktion in einer alten Library wie int myStrLen( char * )
und möchte diese nun verwenden, um die Länge eines const char *
zu ermitteln:
#include <stdio.h> int myStrLen( char * str ) { int l = 0; while( *str++ ) l++; return l; } int main(int argc, char **argv) { char const * text = "Hallo Welt"; int length = myStrLen( text ); printf( "Der Text ist %d Zeichen lang\n", length ); return 0; }
Dieser Quelltext liefert folgende Fehler:
error: invalid conversion from `const char*' to `char*' error: initializing argument 1 of `int myStrLen(char*)'
Hier wäre sicherlich der richtige Weg, die Funktion myStrLen anzupassen, aber nehmen wir an, wir wissen, dass sie das Objekt nicht verändert, doch wir haben den Quelltext nicht vorliegen, weil sie in einer gekauften Library liegt. Um dieses Programm zu kompilieren müssten wir nun entweder eine Kopie des Strings erstellen, was Zeitaufwendig wäre. Um dies zu vermeiden - wenn wir denn wissen, dass die Funktion die übergebenen Parameter nicht verändert - wurde const_cast
erfunden.
Unser Problem mit der myStrLen
-Funktion lässt sich mit einem const_cast
, wie folgt lösen:
int main(int argc, char **argv) { char const * text = "Hallo Welt"; int length = myStrLen( const_cast< char * >( text ) ); printf( "Der Text ist %d Zeichen lang\n", length ); return 0; }
const_cast
muss den gleichen Datentyp zurückgegeben, dass das Objekt besitzt, lediglich der const
-Qualifizierer darf fehlen. Es ist also nicht möglich gleichzeitig const
und den Datentyp zu verändern. In dem Fall sollte const_cast
mit einem static_cast
kombiniert werden, auch wenn ein C-Style-Cast kürzer wäre. Nur mit dieser Ausführlichkeit lässt sich aus dem Quelltext herauslesen, was genau gemeint ist und die Hässlichkeit des Quelltextes an der Stelle markiert deutlich, dass hier etwas passiert, dem man Aufmerksamkeit schenken sollte, wenn man einen Fehler sucht.
Es lassen sich so auch Methoden von Objekten aufrufen, die nicht als Const gekennzeichnet sind. Die Wahrscheinlichkeit, hier Fehler in ein Programm einzubauen steigt allerdings deutlich, denn wäre die Methode für einen const-Zugriff geeignet hätte ein guter Entwickler sie entsprechend markiert!
#include <stdio.h> class Value { int a; public: Value( int value ) : a( value ) {} int add( int b ) { return a+b; } }; int main(int argc, char **argv) { Value const v( 1 ); // Konstantes Objekt int result = v.add( 2 ); printf( "Ergebnis: %d\n", result ); return 0; }
wird mit der Meldung
error: passing `const Value' as `this' argument of `int Value::add(int)' discards qualifiers
belohnt. (siehe auch hier)
Wenn wir sicher sein können, dass das Objekt nicht verändert wird und es nicht möglich ist, die Klasse Value
zu verbessern, dann hilft der const_cast
, in dem wir uns eine Referenz auf das Objekt ohne den const
-Qualifizierer geben lassen:
int result = const_cast< Value & >( v ).add( 2 );
Besser wäre jedoch die Klasse Value
zu verbessern und die Methode add
zu einer Const-Methode zu ändern:
int add( int b ) const { return a+b; }
Hier zeigt sich sehr schön, dass ein Cast in der Regel nur einen Fehler an anderer Stelle kaschiert. Entsprechend selten, möglichst gar nicht, sollten Castings in den eigenen Quelltexten auftreten.
Grundsätzlich lässt sich das Problem an der Überschrift ablesen: const
fehlt beim Datentyp des Parameters einer Funktion oder Methode oder es fehlt das const
bei der Methodendeklaration. Ein const_cast
ist immer nur eine Notlösung, wenn man sich mit einer Library beschäftigten muss, die man nicht ändern kann. Ansonsten sollte man sich besser um die Ursache kümmern, statt Symptome zu behandeln.