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.