84
Konstruktoren / Destruktoren

Konstruktoren / Destruktoren

Embed Size (px)

DESCRIPTION

Konstruktoren / Destruktoren. In C: Initialsieren einer Variable, z.B: int i = 10;. In C++: Initialsieren eines Objekts. Dies geschieht durch den sogenannten Konstruktor. - PowerPoint PPT Presentation

Citation preview

Page 1: Konstruktoren / Destruktoren

Konstruktoren / Destruktoren

Page 2: Konstruktoren / Destruktoren

In C:Initialsieren einer Variable,

z.B:int i = 10;

Page 3: Konstruktoren / Destruktoren

In C++:Initialsieren eines Objekts

Page 4: Konstruktoren / Destruktoren

Dies geschieht durch den sogenannten Konstruktor.

Dies ist eine spezielle Methode in der Klasse mit

dem gleichen Namen wie die Klasse, aber ohne einen

Rückgabewert (auch nicht void).

Page 5: Konstruktoren / Destruktoren

Ein Konstruktor kann (wie jede andere Funktion auch) überladen sein, d.h. es kann mehrere Konstruktoren mit dem gleichen Namen, aber verschiedenen Parametern

-bezogen auf die Anzahl und den Datentyp - geben

Page 6: Konstruktoren / Destruktoren

Konstruktor wird immer dann aufgerufen, wenn ein

Objekt der Klasse instanziert wird.

Page 7: Konstruktoren / Destruktoren

Aufgabe:Erzeugen Sie für die Klasse

Punkt (in einem Koordinatensystem) einen Konstruktor, einmal mit keinem bzw. mit zwei

Parametern.

Page 8: Konstruktoren / Destruktoren

class Punkt{ private: int x; int y;

public: Punkt(); Punkt(int xx, int yy); void set_xy(int xx, int yy); int get_x(); int get_y();}; // class Punkt

Konstruktor kann überladen sein

Konstruktor hat keinen (auch nicht void) Rückgabewert.

Page 9: Konstruktoren / Destruktoren

Punkt::Punkt(){ x = 0; y = 1; }

Punkt::Punkt(int xx, int yy){ set_xy(xx, yy); }

void Punkt::set_xy(int xx, int yy){ x = xx; y = yy; } // gleich geht es weiter. ...

Page 10: Konstruktoren / Destruktoren

int Punkt:: get_x(){ return(x);}

int Punkt::get_y(){ return(y);}

Page 11: Konstruktoren / Destruktoren

Beispiele für das Instanzieren von Objekten:

Page 12: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ int kx, ky; Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

Konstruktor ohne Parameter wird ohne

Klammern aufgerufen

Konstruktor mit Parameter wird mit Klammern

aufgerufen

Page 13: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

Page 14: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

Page 15: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

Page 16: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

Page 17: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

Page 18: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

Page 19: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

Page 20: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

Page 21: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

Page 22: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

Page 23: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

Page 24: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

0 1 3 7 3 7

Page 25: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

0 1 3 7 3 7

Page 26: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

0 1 3 7 3 7

2 4 3 7 3 7

Page 27: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

0 1 3 7 3 7

2 4 3 7 3 7

Page 28: Konstruktoren / Destruktoren

class Punkt{//siehe oben};

int main(){ Punkt p; Punkt q(3, 7); kx = p.get_x(); ky = p.get_y(); kx = q.get_x(); ky = q.get_y(); p.set_xy(2,4); q.set_xy(6,8);}

p.x p.y q.x q.y kx ky

0 1 ? ? ? ?

0 1 3 7 ? ?

0 1 3 7 0 ?

0 1 3 7 0 1

0 1 3 7 3 1

0 1 3 7 3 7

2 4 3 7 3 7

2 4 6 8 3 7

Page 29: Konstruktoren / Destruktoren

0400 2p.y

0408 6q.x0412 8q.y

0404 4p.x

Mögliche Belegung im Arbeitsspeicher:(Annahme: Compiler benötigt 4 Byte für eine Integer-Variable

p

q

Adresse Inhalt

...

Page 30: Konstruktoren / Destruktoren

Ein Konstruktor ohne Argumente (Parameter) wie z.B. Punkt() heisst Standard-Konstruktor.

Page 31: Konstruktoren / Destruktoren

Implementiert der Programmierer für eine Klasse überhaupt keinen Konstruktor, dann erzeugt der Compiler automatisch einen Standard-Konstruktor, der keine Anweisungen besitzt.

Page 32: Konstruktoren / Destruktoren

Hat der Programmierer dagegen mindestens einen Konstruktor (egal mit 0, 1, 2,..., n Parametern) implementiert, erzeugt der Compiler keinen Standard-Konstruktor.

Page 33: Konstruktoren / Destruktoren

Beispiel:

Page 34: Konstruktoren / Destruktoren

class Nagel{ private: int laenge;  public: void set(int l);};

void Nagel::set(int l){ laenge = l;}

int main(){ Nagel n;}

Ist dies korrekt ?Warum ?

Ja, weil der Compiler automatisch einen Standard-Konstruktor erzeugt.

Wie lang ist der Nagel, d.h. welchen Wert hat n.laenge ?

Man weiß es nicht, weil der vom Compiler erzeugte Standard-Compiler keine Anweisung besitzt.

Page 35: Konstruktoren / Destruktoren

Beispiel:

Page 36: Konstruktoren / Destruktoren

class Nagel{ private: int laenge;  public: Nagel(int l) void set(int l);};

void Nagel::set(int l){ laenge = l;}

Nagel::Nagel(int l){ set(l);}

Page 37: Konstruktoren / Destruktoren

int main(){ Nagel n;}

Ist dies korrekt ?Warum ?

Nein, weil der Compiler keinen Standard-Konstruktor erzeugt.

EinStandard-Konstruktor wird aber

beim Instanzieren bei:Nagel n;benötigt !

Page 38: Konstruktoren / Destruktoren

Konstruktoren:Wie wird sichergestellt, dass ein Objekt beim Instanzieren auf jeden Fall initialisiert wird, auch wenn der Programmierer keinen Konstruktor implementiert ?

Page 39: Konstruktoren / Destruktoren

Der Compiler erzeugt einen Standard-Konstruktor.

Page 40: Konstruktoren / Destruktoren

Problem mit Konstruktoren:Objekt enthält als Attribut wieder ein Objekt.Wie ist sichergestellt, dass dieses (eingelagerte) Objekt auch initialisiert wird, selbst wenn der Programmierer es vergisst ?

Page 41: Konstruktoren / Destruktoren

Beispiel:

Page 42: Konstruktoren / Destruktoren

class Punkt{ // wie früher};

class Kreis{ private: Punkt mp; int r;

public: Kreis(int xm, int ym, int a);

}; //class Kreis

Kreis::Kreis(int xm, int ym, int a){ r = a;}

Der Mittelpunkt ist ein Punkt:mp hat den Klassentyp (d.h. Typ ist

eine Klasse) Punkt

Was passiert, wenn der Programmierer den Punkt mp nicht im Konstruktor

Kreis initialisiert ?

Der Radius ist eine Integer-Zahl

Page 43: Konstruktoren / Destruktoren

class Punkt{ // wie früher};

class Kreis{ private: Punkt mp; int r;

public: Kreis(int xm, int ym, int a);

}; //class KreisUnabhängig vom Programmierer werden die eingelagerten Objekte auf jeden Fall vor Eintritt in den Funktionskörper des umgebenden Konstruktors (hier: Kreis) automatisch durch den jeweils zugehörigen Standard-Konstruktor (hier Punkt) jedes eingelagerten Objekts initialisiert.

Page 44: Konstruktoren / Destruktoren

class Punkt{ // wie früher};

class Kreis{ private: Punkt mp; int r;

public: Kreis(int xm, int ym, int a);

}; //class Kreis

Was passiert also, wenn der Programmierer in der Klasse Punkt noch keinen Standard-Konstruktor, aber einen anderen Konstruktor, egal mit wieviel (1, 2, 3, ...) Parametern, implementiert hat ?

Dann erzeugt der Compiler eine Fehlermeldung:Da schon ein Konstruktor existiert, erzeugt der Compiler keinen Standard-Konstruktor mehr. Doch diesen würde er benötigen.

Page 45: Konstruktoren / Destruktoren

Alternative Möglichkeit der Initialisierung eingelagerter Objekte:In der Initialisierungsliste werden die eingelagerten Objekte initialisiert (durch die zugehörigen Konstruktoren

Page 46: Konstruktoren / Destruktoren

Beispiel:

Page 47: Konstruktoren / Destruktoren

class Punkt{ // wie früher};

class Kreis{ private: Punkt mp; int r;

public: Kreis(int xm, int ym, int a);};

Kreis::Kreis(int xm, int ym, int a):mp(xm, ym){ r = a;}

Durch einen Doppelpunkt gefolgt von der Initialisierungsliste werden die eingelagerten Objekte initialisiert.

(durch die zugehörigen Konstruktoren)

Dies geschieht vor Eintritt in den Funktionskörper des umgebenden

Konstruktors (hier: Kreis)

Page 48: Konstruktoren / Destruktoren

int main(){ Kreis k1(10,20,30); Kreis k2(9,7,8);}

Welche Werte haben?k1.mp.x k1.mp.yk1.r

also:k1.mp.x: 10 k1.mp.y: 20k1.r: 30

Es wird aufgerufen:k1(10,20,30) --> k1.mp(10,20)

Page 49: Konstruktoren / Destruktoren

0300 10k1.mp.y

0308 30k1.r0304 20

k1.mp.x

Mögliche Belegung im Arbeitsspeicher:(Annahme: Compiler benötigt 4 Byte für eine Integer-Variable

k1

Adresse Inhalt

...

0312 9k2.mp.y

0320 8k2.r0316 7

k2.mp.xk2

Page 50: Konstruktoren / Destruktoren

Destruktor

Page 51: Konstruktoren / Destruktoren

Ein Destruktor ist in gewisser Weise das Gegenteil eines Konstruktors, weil evtl. vorher im Konstruktor angeforderte Ressourcen (z.B. allokierter Speicherplatz, geöffnete Dateien, usw.) im Destruktor wieder freigegeben werden müssen.

Page 52: Konstruktoren / Destruktoren

Ein Destruktor wird meist dann gebraucht, wenn ein dynamisch allokierter Speicher wieder freigegeben, wenn Dateien wieder geschlossen werden sollen, usw.

Page 53: Konstruktoren / Destruktoren

Ein Destruktor ist eine spezielle Methode in der Klasse mit dem gleichen Namen wie die Klasse und einer vorangestellten Tilde ~ Er hat keinen Parameter und ist ohne einen Rückgabewert (auch nicht void).

Page 54: Konstruktoren / Destruktoren

Jede Klasse kann nur einen Destruktor haben. Er wird automatisch aufgerufen, wenn ein Objekt ungültig (zerstört) wird.

Page 55: Konstruktoren / Destruktoren

Dies ist bei Objekten auf dem Stack im Allgemeinen bei der schließenden Klammer einer Funktion der Fall. Hierzu gehört auch int main(){...}

Page 56: Konstruktoren / Destruktoren

Den Destruktoraufruf kann man sich in der schließenden Klammer der Funktion konzentriert sehen.

Page 57: Konstruktoren / Destruktoren

In der schließenden Klammer } werden Destruktoren für Variable eines Klassentyps aufgerufen, nicht aber für Zeigervariable eines Klassentyps.

Page 58: Konstruktoren / Destruktoren

Ein Destruktor ohne Anweisungen wie z.B.

~Punkt(){}

heisst Standard-Destruktor.

Page 59: Konstruktoren / Destruktoren

Implementiert der Programmierer für eine Klasse keinen Destruktor, dann erzeugt der Compiler automatisch den Standard- Destruktor, der keine Anweisungen besitzt.

Page 60: Konstruktoren / Destruktoren

Beispiel

Page 61: Konstruktoren / Destruktoren

class Test{ public: Test(); Test(int i); ~Test();}; // class Test

benötigt keine Attribute (zu Testzwecken)

Page 62: Konstruktoren / Destruktoren

Test::Test(){ printf("SK aufgerufen\n");}

Test::Test(int i){ printf("SK für int mit Wert %d aufgerufen\n",i);}

Test::~Test(){ printf("Destruktor aufgerufen\n");}

SK bedeutet Standardkonstruktor

Page 63: Konstruktoren / Destruktoren

void machwas(){ printf("Start von machwas\n"); Test t; printf("Ende von machwas\n");}

int main(){ printf("Vor Aufruf von machwas\n"); machwas(); printf("Nach Aufruf von machwas\n");}

In der schließenden Klammer } wird der Destruktor der Klasse Test aufgerufen.

Page 64: Konstruktoren / Destruktoren

Welche Ausgaben erscheinen auf dem

Bildschirm ?

Page 65: Konstruktoren / Destruktoren

Vor Aufruf von machwas

Start von machwas

SK aufgerufen

Destruktor aufgerufen

Nach Aufruf von machwas

Ende von machwas

Page 66: Konstruktoren / Destruktoren

Präzisierung zu vorher (Objekte auf dem Stack):Ein Destruktor wird nicht nur bei der schließenden Klammer einer Funktion, sondern ganz allgemein bei der schließenden Klammer eines Blocks aufgerufen.

Page 67: Konstruktoren / Destruktoren

Beispiel:

Page 68: Konstruktoren / Destruktoren

void machwas(){ int i; for(i=0;i<3;i++){ Test t(i); }}

int main(){ printf("Vor Aufruf von machwas\n"); machwas(); printf("Nach Aufruf von machwas\n");}

Objekt wird innerhalb eines Blocks definiert

Destruktor wird automatisch aufgerufen

Klasse Test wie im obigen Beispiel

Page 69: Konstruktoren / Destruktoren

Welche Ausgaben erscheinen auf dem

Bildschirm ?

Page 70: Konstruktoren / Destruktoren

Vor Aufruf von machwas SK von int mit 0 aufgerufen

Destruktor aufgerufen

Destruktor aufgerufen

SK von int mit 2 aufgerufen

SK von int mit 1 aufgerufen

Destruktor aufgerufen

Nach Aufruf von machwas

Page 71: Konstruktoren / Destruktoren

Konstruktoren und Felder (Arrays)

Page 72: Konstruktoren / Destruktoren

Wird ein Feld von Objekten erzeugt, wird für jedes Element des Feldes ein Konstruktor aufgerufen.

An die Stelle eines Initialisierungswerts tritt nun

eine Liste von Werten.

Page 73: Konstruktoren / Destruktoren

Initialisieren mit einem Standard-Konstruktor.

(Konstruktor mit keinem Parameter).

Page 74: Konstruktoren / Destruktoren

Beispiel:

Page 75: Konstruktoren / Destruktoren

class Punkt{ private: int x; int y;

public: Punkt(); ~Punkt();};

Page 76: Konstruktoren / Destruktoren

Punkt::Punkt(){ x = 10; y = 20;}

Punkt::~Punkt(){}

int main(){

Wenn ein Standard-Konstruktor vorhanden ist (bzw.falls dieser vom Compiler angelegt wird, falls noch kein Konstruktor vom Programmierer erstellt wurde), kann die Initialisiererliste komplett wegfallen:

Punkt p[5];

}

Punkt q[5]={Punkt(),Punkt(),Punkt(), Punkt(), Punkt()};

Die folgende Initialisierung ist genauso möglich

Nach der Initialisierung gilt:p[0].x=10, p[0].y=20, p[1].x=10, p[1].y=20, p[2].x=10, p[2].y=20, p[3].x=10, p[3].y=20,p[4].x=10, p[4].y=20

Page 77: Konstruktoren / Destruktoren

Initialisieren mit einem Konstruktor mit einem

Parameter.

Page 78: Konstruktoren / Destruktoren

Beispiel:

Page 79: Konstruktoren / Destruktoren

class Punkt{ private: int x, y;

public: Punkt(int p); Punkt(int kx, int ky); ~Punkt();};

Page 80: Konstruktoren / Destruktoren

Punkt::Punkt(int p){ x = p; y = p;}

Punkt::Punkt(int kx, int ky){ x = kx; y = ky;}

Punkt:: ~Punkt(){}

int main(){

Wenn ein Konstruktor mit einem Parameter existiert, dann kann die Initialisiererliste aus durch Komma getrennten Werten bestehen.

Punkt p[4] = {13, 17, 19, 5};

}

Punkt q[4] = {Punkt(13),Punkt(17), Punkt(19),Punkt(5)};

Die folgende Initialisierung ist genauso möglich:

Nach der Initialisierung gilt:p[0].x=13, p[0].y=13, p[1].x=17, p[1].y=17, p[2].x=19, p[2].y=19, p[3].x=5, p[3].y=5

Page 81: Konstruktoren / Destruktoren

Initialisieren mit einem Konstruktor mit mehr als

einem Parameter.

Page 82: Konstruktoren / Destruktoren

Beispiel:

Page 83: Konstruktoren / Destruktoren

class Punkt{ private: int x; int y;

public: Punkt(int p); Punkt(int kx, int ky); ~Punkt();};

Page 84: Konstruktoren / Destruktoren

Punkt::Punkt(int p){ x = p; y = p;}

Punkt::Punkt(int kx, int ky){ x = kx; y = ky;}

Punkt::~Punkt(){}

int main(){

Wenn man einem Konstruktor mehr als einen Wert übergeben möchte,muß die Initialisiererliste wie folgt aussehen:

Punkt r[3] = {Punkt(2,3), Punkt(7,8), Punkt(4,9)}; }

Nach der Initialisierung gilt:p[0].x=2, p[0].y=3, p[1].x=7, p[1].y=8, p[2].x=4, p[2].y=9