Konstruktoren, Destruktoren

Bei der Erzeugung eines jeden Objekts zur Laufzeit (für statische Variablen beim Programmstart, für automatische Variablen beim Eintreten in den zugehörigen Block, außerdem beim expliziten Aufruf von new, siehe Freier Speicher new und delete) wird in C++ -ebenso wie bereits in C- ausreichend Speicherplatz für alle vereinbarten Elemente des Objekts zur Verfügung gestellt, nämlich sizeof(...) Bytes. Bei allen globalen sowie bei automatischen initialisierten Variablen wird der neue Speicher außerdem mit 0 oder dem entsprechenden Initialisierungswert beschrieben. Beim Freigeben des Objekts (Verlassen des Blocks bei automatischen Variablen, delete, oder Programmende) wird dieser Speicher wieder freigegeben.

Manchmal sind aber zwischen der Anforderung (z.B. Variablenvereinbarung) und dem erstmaligen Verwenden des Speichers noch weitere Initialisierungen nötig (Öffnen von Dateien, Allokieren von weiterem Speicher, auf den Zeiger in der eben vereinbarten struct zeigen sollen, etc.). Ebenso kann es nötig sein, nach dem letzten Verwenden einer Variablen noch irgendwelche Aufräumarbeiten durchzuführen, beispielsweise Speicher freizugeben oder Dateien zu schließen.

Dies resultiert in C immer in Anweisungen desjenigen, der die entsprechende Datenstruktur kreiert, an den Anwender der Struktur in der Art: ,,Vor dem ersten Verwenden unbedingt die Funktion init_blabla() aufrufen, und nach dem letzten Verwenden auf jeden Fall noch ...`` (Beispiel: vor dem Schreiben und Lesen einer Datei fopen() aufrufen, danach fclose()).

Das ist zum einen lästig für den Anwender, und andererseits extrem fehleranfällig, weil die entsprechenden Tätigkeiten unbedingt synchron zum Geltungsbereich der entsprechenden Objekte erfolgen müssen, der Compiler aber dabei keine Hilfestellung leisten kann. Ein typischer Fall ist die Verwendung von FILE *. Wenn man dabei nicht die richtige Reihenfolge von fopen(), fclose() und der restlichen Verwendung einhält, dann hat man verloren.

In C++ hat man dafür eine wesentlich elegantere Möglichkeit: Neben dem erwähnten automatischen Beschaffen und Freigeben von Speicher kann man sich zu jeder Klasse bei Bedarf einen Konstruktor und/oder einen Destruktor definieren. Der Konstruktor wird dann bei jedem Erzeugen eines Objekts (aber nicht beim Beschaffen des entsprechenden Speichers mit malloc(), calloc() und realloc()!) aufgerufen, der Destruktor entsprechend beim Verlassen des jeweiligen Geltungsbereichs.

Der Name des Konstruktors ist identisch mit dem Namen der entsprechenden Klasse; der Destruktor hat dazu noch ein vorangestelltes ~. Beide werden ohne einen bestimmten Rückgabewert definiert.

Anstatt Konstruktor wird auch oft der Begriff ctor (als Kurzform des englischen constructor) verwendet; anstatt Destruktor entsprechend dtor (für destructor).

Konstruktoren kann man auch überladen, um eine Initialisierung mit oder ohne Parametern zu ermöglichen. Ein Beispiel folgt in Überladen von Operatoren.

Wie ein Konstruktor die Elemente der Klasse initialisieren kann, ist in Initialisierung der Klassenelemente beschrieben.



Unterabschnitte
AnyWare@Wachtler.de