C++ Templates Übersicht Warum Templates? Anderes Beispiel

Übersicht
• Warum
Datenstrukturen
Warum
Templates?
Templates?
und Klassen
• Funktionstemplates
Zugriffskontrolle
C++
• Klassentemplates
Operationen: Methoden
• Abschliessende
Klassenweite Elemente
Bemerkungen
Templates
• Konstruktoren und Destruktoren
• Überladen von Operatoren
• Mehr zu Klassen
c und c++ • c++ templates • gerrit burkert • 06/2006 •
1
Warum Templates?
c und c++ • c++ templates • gerrit burkert • 06/2006 •
2
Anderes Beispiel
• Alternative Präprozessor?
// Gleiche Funktion fuer verschiedene
// Datentypen
#define max(a,b) ((a > b) ? a : b)
int max(int i1, int i2) {
if (i1 > i2)
• Beim Einsatz von Präprozessor-Makros können eine Reihe von
Problemen auftauchen, weshalb man diese besser vermeidet
return i1;
return i2;
}
• Zur Erinnerung:
double max(double d1, double d2) {
if (d1 > d2)
#define quad(a) ((a)*(a))
return d1;
y = quad(x++);
return d2;
}
c und c++ • c++ templates • gerrit burkert • 06/2006 •
3
c und c++ • c++ templates • gerrit burkert • 06/2006 •
4
Anderer Ansatz mit einem Makro
Anderer Ansatz mit einem Makro
1. Definition phase
3. Use phase:
#define make_max(type) type max(type d1, type d2) { \
int main() {
if (d1 > d2) \
return (d1); \
return (d2); \
}
float f
int i
=
=
max(3.5, 8.7);
max(100, 800);
char ch
=
max('A', 'Q');
}
2. Generation phase
• So funktioniert es ganz brauchbar für einfache Funktionen
• Nachteil: Das Makro define_max muss für jeden Typ, der
verwendet werden soll, ausgeführt werden
make_max(int);
make_max(float);
make_max(char);
c und c++ • c++ templates • gerrit burkert • 06/2006 •
5
Templates
c und c++ • c++ templates • gerrit burkert • 06/2006 •
6
Templates
• Ziel also: flexiblere Funktionen, die für unterschiedliche
Typen einsetzbar sind
• Templates können eingesetzt werden, um den gleichen
Code für verschiedene Typen verwenden zu können
• Weiteres Ziel: flexiblere Klassen, die für unterschiedliche
Typen einsetzbar sind
• Je nach benötigten Typen wird dann unterschiedlicher
Programmcode generiert (Polymorphismus)
• So wäre es sinnvoll einen Stack für beliebige Objekttypen zu haben, ihn aber nur einmal definieren zu
müssen
• Im Gegensatz zum späten Binden werden die Typen der
Templates aber beim Kompilieren festgelegt:
parametrisierbarer Polymorphismus, ÜbersetzungszeitPolymorphismus
=> Einsatz von Funktions- und Klassentemplates
• Wenn für ein Template Code für einen spezifischen Typ
generiert wird, wird das Template instanziiert
c und c++ • c++ templates • gerrit burkert • 06/2006 •
7
c und c++ • c++ templates • gerrit burkert • 06/2006 •
8
Übersicht
Funktionstemplates
1. Definition phase
• Warum Templates?
template<class T>
• Funktionstemplates
T max(T d1, T d2) {
• Klassentemplates
if (d1 > d2)
return (d1);
• Abschliessende Bemerkungen
return (d2);
}
2. Generation phase
Automatic :-)
c und c++ • c++ templates • gerrit burkert • 06/2006 •
9
Funktionstemplates
template<class T>
T max(T d1, T d2) {
if (d1 > d2)
return (d1);
return (d2);
}
int main() {
=
max(3.5, 8.7);
int i
=
max(100, 800);
char ch
=
max('A', 'Q');
int i2
=
max(600, 200);
10
Template-Definition
3. Use phase:
float f
c und c++ • c++ templates • gerrit burkert • 06/2006 •
}
Das Schlüsselwort template eröffnet eine TemplateArgumentliste
c und c++ • c++ templates • gerrit burkert • 06/2006 •
11
c und c++ • c++ templates • gerrit burkert • 06/2006 •
12
Template-Definition
Beispiel
• Der Name für den Typ ist dabei unerheblich
template <class T>
inline T max(T a, T b) { return a > b ? a : b; }
• Die Funktionsdeklaration oder -definition kann diese
Typen als bekannt benutzen
int main()
int x, y = 3, z = 4;
• Die Gültigkeit des Alias beschränkt sich auf den
folgenden Block
double a, b = 1.4, c = 7.3;
short m, n = 6, o = 9;
• Operationen auf diesen Typ werden als vorhanden
angenommen
• Der Compiler erzeugt für jeden Typ, den die Funktion
anfordert eine eigene Kopie
c und c++ • c++ templates • gerrit burkert • 06/2006 •
{
x = max(y, z);
// max(int, int)
a = max(b, c);
// max(double, double)
m = max(n, o);
// max(short, short)
x = max(y, o);
// ...max(int, short) ???? Fehler!
}
13
Beispiel
c und c++ • c++ templates • gerrit burkert • 06/2006 •
14
Template-Auflösung
• Die Erzeugung von Funktionen mit Templates ist also
nicht mit dem Schreiben der entsprechenden Funktionen
äquivalent:
Aufrufe werden vom Compiler nach folgender Strategie
aufgelöst:
1. Der Compiler sucht nach einer existenten Funktion, die
in den Parametern exakt übereinstimmt
Es wird keine implizite Typumwandlung durchgeführt
– Dabei sind triviale Umwandlungen wie z.B. T nach
T& oder T* nach T[] möglich
• Mögliche Lösung:
– Explizite Typumwandlung beim Aufruf
– Existieren mehrere derartige Funktionen wird eine
Fehlermeldung wegen Mehrdeutigkeit ausgegeben
x = max(y, int(o));
– Angabe des Typs beim Aufruf
x = max<int>(y, o);
// max(int, int)
c und c++ • c++ templates • gerrit burkert • 06/2006 •
15
c und c++ • c++ templates • gerrit burkert • 06/2006 •
16
Template-Auflösung
Mehrere Typen
2. Der Compiler sucht nach einem Funktionstemplate, das
die entsprechende Funktion mit der betreffenden
Argumentliste erzeugen kann
• Ein Template kann auch mit mehreren Typen
definiert werden
template <class T1, class T2>
– Auch hier wird bei Mehrdeutigkeiten ein Fehler
ausgegeben
inline T1 max(T1 a, T2 b) {
return a > b ? a : c;
3. Nach den üblichen Regeln wird versucht, eine
überladene Funktion zu finden
c und c++ • c++ templates • gerrit burkert • 06/2006 •
}
17
Mehrere Typen
int
c und c++ • c++ templates • gerrit burkert • 06/2006 •
18
Mehrere Typen
• Es werden wesentlich mehr Funktionen generiert
main() {
int x, y = 3, z = 4;
• Problem: Rückgabetyp hängt von der Reihenfolge des
Aufrufs ab, da immer ein Wert vom ersten Typ
zurückgegeben wird
double a, b = 1.4, c = 7.3;
short m, n = 6, o = 9;
x = max(y, z);
// max(int, int)
a = max(b, c);
// max(double, double)
m = max(n, o);
// max(short, short)
x = max(y, o);
// max(int, short)
x = max(o, y);
// max(short, int)
• Es ist nicht möglich nur für den Rückgabewert einen
Template-Typ zu verwenden, da Funktionen nicht
anhand ihres Rückgabewertes unterscheidbar sind
// nicht zulässig:
template <class T1, class T2, class T3>
}
T1 max(T2 a, T3 b) { return a > b ? a : b; }
c und c++ • c++ templates • gerrit burkert • 06/2006 •
19
c und c++ • c++ templates • gerrit burkert • 06/2006 •
20
Templatefunktionen überladen
Templatefunktionen überladen
• Template-Funktionen können nach den üblichen Regeln
überladen werden
• Überladen von Template-Funktionen ist nur erlaubt, wenn
dadurch keine Mehrdeutigkeiten entstehen
• Ein Aufruf der Funktion max aus dem Beispiel ist für
Strings (char *) nicht sinnvoll: Es würde nur der
Pointerwert verglichen
template <class T>
nicht kombinierbar
inline T f(T a, T b) { ... }
template <class T1, class T2>
inline T1 f(T1 a, T2 b) { ... }
• Es ist aber problemlos möglich, für Strings unabhängig
vom Template eine eigene Funktion zu schreiben
template <class T>
inline T f(T a, T b, int c) { ... }
inline char* max(char* a, char* b) {
return strcmp(a, b) > 0 ? a : b;
}
c und c++ • c++ templates • gerrit burkert • 06/2006 •
ok
21
Übersicht
c und c++ • c++ templates • gerrit burkert • 06/2006 •
22
Klassentemplates
• Ohne Templates möglich:
Listenklasse, die Objekte vom Typ Person verwaltet
• Warum Templates?
• Funktionstemplates
• Wünschenswert wäre eine Liste für beliebige Objekte
• Klassentemplates
• Ebenso für einen Stack
• Abschliessende Bemerkungen
• Möglich mit Klassentemplates
(auch parametrisierte Klassen genannt)
c und c++ • c++ templates • gerrit burkert • 06/2006 •
23
c und c++ • c++ templates • gerrit burkert • 06/2006 •
24
Beispiel (Teil 1)
Beispiel (Teil 2)
template <class T> class Liste;
// Vorausdeklaration
template <class T>
template <class T>
class Liste
class Listenelement {
friend class Liste<T>; // Liste soll Zugriff haben
Liste();
public:
// Neue leere Liste
~Liste() { delete root; } // Liste löschen
Listenelement(T k, Listenelement* le = 0) : data(k),
void einfuegen(T k);
next(le) {};
// Objekt vorne einfügen
private:
~Listenelement() { delete next;}
Listenelement<T>* root;
private:
T data;
{
public:
// Wurzel der Liste
};
// Der eigentliche Datensatz
Listenelement* next; // Zeiger auf nächstes Element
};
c und c++ • c++ templates • gerrit burkert • 06/2006 •
25
Klassentemplates
c und c++ • c++ templates • gerrit burkert • 06/2006 •
26
Beispiel (Teil 3)
template <class T>
• Aufbau analog zu den Funktionstemplates: Hier steht
die template-Anweisung vor einer Klassendeklaration
Liste<T>::Liste()
root = 0;
{
// Noch kein Listenelement angehaengt
• Bei der Definition der Methoden muss vor jede
Definition wieder eine template-Anweisung stehen
}
• Auch in der Klassenbezeichnung muss der Typ der
Klasse angegeben werden
template <class T>
void Liste<T>::einfuegen(T k)
{
Listenelement<T>* neu = new Listenelement<T>(k, root);
root = neu;
}
c und c++ • c++ templates • gerrit burkert • 06/2006 •
27
c und c++ • c++ templates • gerrit burkert • 06/2006 •
28
Klassentemplate verwenden
Beispiel (Teil 4)
int main()
• Bei der Erzeugung von Objekten muss angegeben
werden, welchen Typ die Template-Variable haben
soll
{
Liste<int> k;
// Generierung einer int-Liste
k.einfuegen(3);
k.einfuegen(5);
• Der Typ wird in spitzen Klammern hinter dem
Klassennamen angegeben
k.einfuegen(7);
Liste<double> l;
// Generierung einer double-Liste
l.einfuegen(3.5);
Liste<int>
intListe;
Liste<Person>
personenListe;
l.einfuegen(5.0);
l.einfuegen(7);
return 0;
}
c und c++ • c++ templates • gerrit burkert • 06/2006 •
29
Parameter von Klassentemplates
c und c++ • c++ templates • gerrit burkert • 06/2006 •
30
Parameter von Klassentemplates
• Ausser der Angabe eines Typs in einem Klassentemplate
können auch weitere Parameter übergeben werden
• Beim Erzeugen von Objekten der Arrayklasse müssen
nun zwei Parameter übergeben werden
• Beispiel: Übergabe der Grösse bei einer Arrayklasse
template<class
<classT,T>
template
int Groesse>
class Array
Array { {
class
public:
T a[??];
// wie groß soll das Array sein?
T a[Groesse];
....
Array<int, 10>;
// int Array, 10 Elemente
Array<double, 10>;
// double Array, 10 Elemente
Array<int, 5>;
// int Array, 5 Elemente
Array<double, 5>;
// double Array, 5 Elemente
public:
};
• Hier handelt es sich um vier verschiedene Klassen
....
};
c und c++ • c++ templates • gerrit burkert • 06/2006 •
31
c und c++ • c++ templates • gerrit burkert • 06/2006 •
32
Klassentemplates spezialisieren
Statische Elemente
• Das Überladen von Klassentemplates ist nicht erlaubt
• Auch Templateklassen können statische Elemente
haben
• Es ist auch nicht erlaubt, dass nicht parametrisierte
Klassen und parametrisierte Klassen denselben Namen
tragen
• Dabei wird für jeden Typ ein eigenes statisches
Element erzeugt
• Erlaubt sind dagegen Spezialisierungen für spezielle
Typen:
template <class T>
class X
class X<char>
{
public:
char ch;
T t;
};
{
public:
int operator==(X<char>);
};
c und c++ • c++ templates • gerrit burkert • 06/2006 •
33
Ableitung von Klassentemplates
c und c++ • c++ templates • gerrit burkert • 06/2006 •
34
Ableitung von Klassentemplates
Verschiedene Fälle zu unterscheiden:
Die Basis ist nicht parametrisiert dafür aber die abgeleitete
Klasse
Die Basis ist parametrisiert, die abgeleitete Klasse nicht
class Basis {};
template <class T>
template <class T>
class Basis { public : T x; };
class Abgeleitet : public Basis {};
class Abgeleitet : public Basis<typ> {};
c und c++ • c++ templates • gerrit burkert • 06/2006 •
35
c und c++ • c++ templates • gerrit burkert • 06/2006 •
36
Ableitung von Klassentemplates
Übersicht
Basis und abgeleitete Klasse sind parametrisiert
• Warum Templates?
• Funktionstemplates
template <class T>
• Klassentemplates
class Basis { public : T x; };
• Abschliessende Bemerkungen
template <class T>
class Abgeleitet : public Basis<T> {};
c und c++ • c++ templates • gerrit burkert • 06/2006 •
37
Schlussbemerkungen
• Die Kombination von Templates mit anderen Sprachmitteln
kann relativ kompliziert werden
– mehrfache Ableitung und virtuelle Funktionen
– Aufteilung in Header- und Source-Dateien
• Gut eingesetzt verringern Templates die Redundanz und
erhöhen die Übersichtlichkeit von Programmen
c und c++ • c++ templates • gerrit burkert • 06/2006 •
39
c und c++ • c++ templates • gerrit burkert • 06/2006 •
38