Const-Correctness

Die meisten Programmiersprachen benutzen entweder konstante, unveränderliche Objekte, die zu neuen Objekten kopiert und verändert werden oder sie verwenden Objekte die veränderlich sind.

C++ beherrscht den Umgang mit beidem Varianten.

Möchte man ein Objekt als unveränderlich kennzeichnen, so schreibt man const hinter den Part, den man unveränderlich halten möchte:

int                 variableValue;
int const           constantValue;
 
int       *         pointerToVariableValue;
int const *         pointerToConstantValue;
int       * const   constantPointerToVariableValue;
int const * const   constantPointerToConstantValue;
 
int const * const * variablePointerToConstantPointerToConstantValue;

Häufig findet sich auch folgende Schreibweise

int                 variableValue;
const int           constantValue;
 
      int *         pointerToVariableValue;
const int *         pointerToConstantValue;
      int * const   constantPointerToVariableValue;
const int * const   constantPointerToConstantValue;
 
const int * const * variablePointerToConstantPointerToConstantValue;

Es sei jedoch zur ersten Schreibweise geraten. Schon alleine, weil es deutlich einfacher gleiche Datentypen zu erkennen, wenn sie untereinander stehen, aber trotzdem am Anfang der Zeile.

Im Quelltext werden die Datentypen meist am Anfang der Zeile geschrieben, was dann weniger lesbar ist. Üblicherweise findet man Deklarationen etwa so vor:

int variableValue;
const int constantValue;
 
int * pointerToVariableValue;
const int * pointerToConstantValue;
int * const constantPointerToVariableValue;
const int * const constantPointerToConstantValue;
 
const int * const * variablePointerToConstantPointerToConstantValue;

Es ist offensichtlich, dass der Aufwand lesbar zu schreiben überschaubar ist und viel bringt.

Aber es gibt noch einen weiteren, noch wichtigeren Grund const hinter den Datentyp zu setzen: Im Fall von variablePointerToConstantPointerToConstantValue ist beim zweiten const nämlich erstmal die Frage, auf welchen * es sich bezieht. Das const vorne bezieht sich auf das nachfolgende Wort, das zweite const auf den vorhergehenden Stern. Die Aussage ist gleichwertig, doch sollte man versuchen, sich eindeutig auszudrücken.

Der pointerToConstant darf nun nicht mehr verwendet werden, um den Integer auf den gezeigt wird, zu verändern. Aber der Pointer darf jederzeit neu gesetzt werden. Eine Konstante darf nur bei der Deklaration gesetzt werden und ist ab dann konstant.

Bei constantPointerToVariableValue ist die Sache genau umgekehrt. Der Zeiger ist konstant, nachdem er initialisiert wurde, darf er nicht mehr auf ein anderes Integer zeigen. Das Integer selbst darf aber jederzeit verändert werden. Die constantPointer…' müssen also genauso wie constantValue'' sofort initialisiert werden, entweder durch direkte Zuweisung bei der Deklaration oder durch Aufruf in der Initialisierungsliste. Innerhalb von Klassen ist die direkte Zuweisung jedoch nur bei Zeigern, Integern (char, short, long, int) und Fließkommazahlen (float, double) erlaubt. Abstraktere Objekte können so in der Klasse nicht konstruiert werden.

Wir sehen, dass es in C++ möglich ist, ganz genau auszudrücken, was wo verändert werden darf. Dies lässt sich nun für eine ganze Reihe von Fehlermöglichkeiten ausnutzen, um sichere und stabilere Programme zu schreiben.