Beginn der Lebenszeit einer Variablen:
Ende der Lebenszeit einer Variablen:
Für primitive Datentypen sind Konstruktoren und Destruktoren sehr einfach. Der Compiler kennt sie und wendet sie automatisch an. Initialisierung kann auf drei verschiedenen Arten spezifiziert werden:
initializer: '=' assignment_expression | '=' '{' initializer_list '}' | '(' expression_list ')' .
C++ Reference Manual
Die ``= expression''-Notation stammt aus C:
int i = 7; complex z = complex(3.4,6); char *p = "hallo\n";
Die ``= initializer_list''-Notation ist ebenfalls aus C. Sie dient zur Initialisierung von Arrays und Structures:
struct studi { char *name; long matrnr; } st_liste[] = {"Adam", 3567890, "Eva", 3678901};
Die ``(expression_list)''-Notation stammt aus Simula. Wird meist für nicht-arithmetische Typen genommen:
date today(25,4,1994);
Die Notationen 1 und 3 sind austauschbar (Geschmacksache):
int i(7); date today = date(25,4,1994); complex z(3.4,6);
Bei fehlender Initialisierung werden
Müssen vom Klassen-Designer zur Verfügung gestellt werden.
Konstruktoren haben den selben Namen wie die Klasse. Sie haben keinen Ergebnistyp und dürfen auch kein Ergebnis liefern.
class date { int day, month, year; public: date(int, int, int); // Konstruktor-Dekl. void print(); }; // Konstruktor-Definition: date::date(int d, int m, int y) { // Initialisierung durch Wertzuweisung: day = d; month = m; year = y; } ... date xmax(24,12,1997); // Simula-Stil date today = date(17,4,1997); // C-Stil
Wie Elementfunktionen darf der Konstruktor auch innerhalb der Klassendeklaration definiert werden.
Eine andere Möglichkeit für die Initialisierung der Klassenelemente:
class date { int day, month, year; public: date(int, int, int); // Konstruktor-Dekl. void print(); }; // Konstruktor-Definition: date::date(int d, int m, int y) : day(d), month(m), year(y) {}
Diese Initialisierungsliste initialisiert die Klassenelemente mit deren Konstruktor. Im Rumpf des Konstruktors ist in unserem Beispiel nichts mehr zu tun.
Es darf beliebig viele Konstruktorfunktionen geben. Sie müssen in Anzahl und/oder Typ der Parameter unterscheidbar sein.
class date { int day, month, year; public: date(int, int, int); // Konstruktor-Dekl. date(int); // Konstruktor-Dekl. void print(); }; // Konstruktor-Definitionen: date::date(int d, int m, int y) : day(d), month(m), year(y) {} date::date(int y) : year(y), day(1), month(1) {} ... date newyear(1999);
Ein Default-Konstruktor ist ein Konstruktor ohne Parameter:
class date { int day, month, year; public: date() { day=1; month=1; year=1956;} };
Der Default-Konstruktor wird aufgerufen für
date tomorrow;
date* urlaub = new date[29];
class geburtstag { char *name; date geboren; ... }wenn sie nicht von deren Konstruktoren explizit konstruiert werden.
Wenn eine Klasse überhaupt keinen Konstruktor hat, wird der Default-Konstruktor vom Compiler generiert:
class date { int day, month, year; }; ... date irgendwann; // OK, aber unschoen!
Existiert jedoch ein Konstruktor, muß auch der Default-Konstruktor angegeben werden (wenn er benutzt wird):
class date { int day, month, year; public: date(int d, int m, int y) : day(d),month(m) ,year(y) {}; }; ... date irgendwann; // FEHLER!
COMPILER:
Too few arguments for constructor `date' Compilation failed
Der Copy-Konstruktor hat folgende Aufgaben:
date today(25,4,1994); date heute = today;
void remember(date d); ... remember(today);
date nextparty() { ... return libori; }
Ein Copy-Konstruktor für Klasse X hat die Form
X::X(const X&) // konstanter Referenzparameter
Wenn kein Copy-Konstruktor angegeben wird, wird er vom Compiler generiert. Der generierte Copy-Konstruktor erzeugt elementweise Kopien der Datenelemente des Objekts.
Ein selbstgeschriebener Copy-Konstruktor
date(const date& original) { day=original.day; month=original.month; year=original.year; cout << "Handmade Copy Constructor\n"; } /* date */
Eigene Copy-Konstruktoren werden in der Regel nötig, wenn die Objekte dynamische Daten enthalten.
Beispiel:
class student { char *name; int matrnr; public: student(char *, int); // Konstruktor void gross(void); void print(); }; void student::gross(void) { *name = *name - ' '; } void student::print() { cout << name << " " << matrnr << "\n"; } ... student erika("mustermann",3567890); student clone = erika; erika.gross(); clone.print(); // Schreibt "Mustermann"
Elementweises Kopieren genügt nicht.
Copy-Konstruktor selbst schreiben (z.B. mit strcpy).