Programmieren II Klassen Programmieren II Klassen

Werbung
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Konstruktoren
Ziel dieses Abschnitts
•
keine Zusammenfassung, aber
•
•
Wiederholung von einigen relevanten Aspekten (/* Aufgreifen
von Fragen/Problemen beim Lösen der Praktikumsaufgaben */)
Diskussion eines Aspekts, den wir bisher „fast“ vollständig
ausgeklammert haben
•
jede Klasse hat einen Default-Konstruktor
•
wird aufgerufen, wenn ein Objekt von diesem Typ (/* eine
Instanz dieser Klasse */) erzeugt wird
sobald ein eigener Konstruktor deklariert wird, steht dieser
Default-Konstruktor nicht mehr zur Verfügung
•
manchmal ist es sinnvoll, diesen Default-Konstruktor
wieder verfügbar zu machen
9/1
Programmieren II
Klassen
9/2
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Beispiel
class Bruch {
private:
int zaehler_;
int nenner_;
public:
Bruch(int, int);
void display();
};
Beispiel
...
Bruch bruch1;
diese Anweisung erzeugt eine
Fehlermeldung !!!
... besser ...
int x = 7;
int y = -21;
Bruch br1(3,3);
Bruch br2(x,y);
class Bruch {
private:
int zaehler_;
int nenner_;
public:
Bruch( ) { };
Bruch(int, int);
void display();
};
Default-Konstrukor re-definieren
einzige Möglichkeit, ein Objekt
vom Typ Bruch zu erzeugen
9/3
Hinweis: hierbei handelt es sich um ein sehr einfache Variante einer
so genannten inline-Funktion
9/4
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Destruktoren
•
•
Beispiel
jede Klasse hat einen Default-Destruktor
•
wird automatisch (/* !!! */) aufgerufen, wenn ein Objekt
von diesem Typ zerstört wird (/* etwa beim Verlassen des
Blocks, in dem das Objekt erzeugt wurde bzw. beim
Beenden des Programms */)
manchmal ist es sinnvoll, diesen Default-Destruktor zu redefinieren
•
Verwendung von Klassen-Variablen (/* in der Klassendeklaration mit dem Schlüsselwort static versehen */)
•
Verwendung von dynamischen Datenelementen
selbstdeklarierter
Destruktor
class Konto {
private:
const string inhaber_;
int nummer_;
double stand_;
static double zinssatz_;
static int anzahl_;
public:
Konto(string, int, double);
void display( );
void einzahlen(double);
void abschluss();
static int get_anzahl();
static void set_zinssatz(double);
~Konto( );
};
9/5
9/6
Hinweis: einen Destruktor sollte man nicht „selbst“ aufrufen
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Beispiel
Ergänzende Bemerkungen
Konto::Konto (string s, int n, double a) : inhaber_(s) {
nummer_ = n;
stand_ = a;
++anzahl_;
}
Beispiel
class Konto {
private:
...
static double zinssatz_;
static int anzahl_;
public:
...
};
Konto::~Konto ( ) {
--anzahl_;
}
Hinweis: Klassenvariablen müssen (/* außerhalb der Klassendeklaration */)
separat definiert und initialisiert werden (/* sie spielen die Rolle von
globalen Variablen und sollen auch dann verfügbar sein, wenn noch
kein Objekt der Klasse existiert */)
... stellt sicher, daß der Wert der Klassenvariable anzahl_ die Anzahl der
aktuell verfügbaren Objekte vom Typ Konto korrekt widerspiegelt
9/7
double Konto::zinssatz_ = 3.3;
int Konto::anzahl_ = 0;
9/8
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Beispiel‘
selbstdeklarierter
Destruktor
Beispiel‘
class Polynom {
private:
Term * first_;
public:
Polynom( );
~Polynom( );
void display( );
void add_term( int, int );
double evaluate( double );
};
Polynom::~Polynom( ) {
Term * ptr_term = first_;
Term * help = NULL;
while ( ptr_term != NULL ) {
help = (*ptr_term).get_next();
delete ptr_term;
ptr_term = help;
}
}
9/9
Programmieren II
Klassen
9/10
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Kopier-Konstruktoren
•
•
Beispiel
jede Klasse hat einen Default-Kopier-Konstruktor
•
wird automatisch (/* !!! */) aufgerufen, wenn ein Objekt
kopiert werden soll (/* etwa explizit durch eine
entsprechende Zuweisung bzw. bei der Abarbeitung einer
Methode */)
manchmal ist es sinnvoll, diesen Default-Kopier-Konstruktor
zu re-definieren
•
Verwendung von dynamischen Datenelementen
Bruch summe( Bruch, Bruch );
class Bruch {
private:
int zaehler_;
int nenner_;
public:
Bruch( int, int );
void display( );
};
expliziter Aufruf bei einer Zuweisung
Bruch br1(3,4);
Bruch br2 = br1;
impliziter Aufruf bei Abarbeitung einer
Funktion (/* Methode */)
Bruch br1(3,4);
Bruch br2(1,5);
Bruch erg = summe(br1,br2);
9/11
9/12
Hinweis: der Default-Kopier-Konstruktor kopiert „einfach“ die Datenelemente
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Beispiel‘
class Polynom {
private:
Term * first_;
public:
Polynom( );
~Polynom( );
void display( );
void add_term( int, int );
double evaluate( double );
};
Beispiel‘
impliziter Aufruf bei Abarbeitung einer
Methode
expliziter Aufruf bei einer Zuweisung
class Polynom1 {
private:
Term * first_;
public:
Polynom1( );
~Polynom1( );
void display( );
void add_term( int, int );
double evaluate( double );
void add_poly(Polynom1);
};
Polynom poly1;
Polynom poly2 = poly1;
erzeugt Laufzeitfehler !!!
Polynom1 poly1;
Polynom1 poly2;
poly1.add(poly2);
erzeugt Laufzeitfehler !!!
9/13
9/14
dramatischer, weil man sich dieses Problem ggf. gar nicht bewußt ist !!!
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Beispiel‘ (/* Lösung 1 ... Problem umgehen */)
Beispiel‘ (/* Lösung 2 */)
class Polynom3 {
private:
Term* first_;
public:
Polynom3( );
~Polynom3( );
Polynom3( Polynom3 & );
void add_term( int, int );
...
};
class Polynom2 {
private:
Term * first_;
public:
Polynom2( );
~Polynom2( );
void display( );
void add_term( int, int );
double evaluate( double );
void add_poly(Polynom2 &);
};
Deklaration des eigenen
Kopier-Konstruktors
wichtig!!!
9/15
Hinweis: immer von der Form
9/16
Klassenname( Klassenname & );
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Beispiel‘
siehe
Konstruktor
Ergänzende Bemerkungen
Polynom3 poly1;
Polynom3 poly2(poly1);
Definition des eigenen Kopier-Konstruktors
Polynom3::Polynom3( Polynom3 & poly ) {
Term * dummy = new Term;
(*dummy).set_ex(-1);
(*dummy).set_ko(0);
(*dummy).set_next(NULL);
first_ = dummy;
Term * help = poly.get_first();
help = (*help).get_next();
int e, k;
while ( help != NULL ) {
e = (*help).get_ex();
k = (*help).get_ko();
add_term(e,k);
help = (*help).get_next();
}
}
poly1.first_
-1
0
0
3
3
-7
siehe Methode
add_term 9/17
Programmieren II
Klassen
9/18
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Polynom3 poly1;
Polynom3 poly2(poly1);
Polynom3 poly1;
Polynom3 poly2(poly1);
poly1.first_
poly1.first_
-1
0
0
3
3
-7
poly2.first_
das macht C++ für uns; Erzeugung des Objekts vom Typ Polynom3
-1
0
-1
0
0
3
3
-7
poly2.first_
9/19
9/20
Programmieren II
Klassen
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Polynom3 poly1;
Polynom3 poly2(poly1);
Polynom3 poly1;
Polynom3 poly2(poly1);
help
poly1.first_
-1
0
0
3
help
poly1.first_
3
-7
poly2.first_
-1
0
0
3
-1
0
0
3
3
-7
poly2.first_
-1
0
9/21
Programmieren II
Klassen
9/22
Programmieren II
Klassen
Ergänzende Bemerkungen
Ergänzende Bemerkungen
Polynom3 poly1;
Polynom3 poly2(poly1);
Polynom3 poly1;
Polynom3 poly2(poly1);
help
poly1.first_
-1
0
0
3
help
poly1.first_
3
-7
poly2.first_
-1
0
0
3
3
-7
-1
0
0
3
3
-7
poly2.first_
-1
0
0
3
9/23
9/24
Programmieren II
Klassen
Ergänzende Bemerkungen
Polynom3 poly1;
Polynom3 poly2(poly1);
help
poly1.first_
-1
0
0
3
3
-7
-1
0
0
3
3
-7
poly2.first_
9/25
Herunterladen