Ü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
© Copyright 2024 ExpyDoc