Programmieren - C++ Templates

Ähnliche Dokumente
Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

Ziel, Inhalt. Programmieren in C++ Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind

Objektorientierte Programmierung mit C++ SS 2007

Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Gute Lösung:

DAP2-Programmierpraktikum Einführung in C++ (Teil 1)

Deklarationen in C. Prof. Dr. Margarita Esponda

Angewandte Mathematik und Programmierung

Angewandte Mathematik und Programmierung

Fortgeschrittene C++-Programmierung

Objektorientiertes Programmieren für Ingenieure

C++ - Funktionen und mehr. Kerstin Gößner und Ralf Wondratschek

C++ Kurs Teil 1. Architektur, Anwendungsspektrum, primitive Datentypen, Funktionsaufrufe, Referenzen, Klassen

C++-Zusammenfassung. H. Schaudt. August 18, 2005

C++ - Einführung in die Programmiersprache Polymorphismus und Vererbung. Eltern

Der C++ Crashkurs v1.0

2. Semester, 2. Prüfung, Lösung

Einführung in die C++ Programmierung für Ingenieure

13. Vererbung. Prof. Dr. François E. Cellier Informatik I für D-ITET (HS 2012)

Einführung in C++ mit Microsoft VS

C vs. C++ Sebastian Meyer. Proseminar C - Grundlagen und Konzepte. Universität Hamburg

Vorkurs C++ Programmierung

Programmieren - Vererbung & Polymorphie

Objektorientierte Programmierung mit C++ Vector und List

Funktionen und Parameter

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 18

In der Computersprache C ist die Standardmethode zur Behandlung von Matrizen durch

Es gibt zwei verschiedene Arten, wie Programme auf dem Rechner ausgeführt werden:

12. Vererbung. Prof. Dr. Markus Gross Informatik I für D-ITET (WS 03/04)

Einführung in die Programmiersprache C

5.4 Klassen und Objekte

Grundlagen der Informatik - 6. Praktikum

Javakurs für Anfänger

1 Polymorphie (Vielgestaltigkeit)

Zusammengesetzte Datentypen -- Arrays und Strukturen

Einführung in die C-Programmierung

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 16

Z:\Informatik 3\Labor_GINF3\Labor_01-Sonstiges.txt

Informatikpraktikum CE2. Übung 1: Einfach verkettete Liste

Eine Einführung in C-Funktionen

Alltagsnotizen eines Softwareentwicklers

Grundlagen C und C++ Einheit 03: Grundlagen in C++ Lorenz Schauer Lehrstuhl für Mobile und Verteilte Systeme

Einführung in die Programmierung (EPR)

Monte Carlo Simulationen

(allgemeine) OOP in C++ Klassen und header-files Konstruktorn / Destruktoren Speicherverwaltung C++ Standard Library / SLT

Meeting C++ C++11 R-Value Referenzen

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek

Programmieren II Klassen. Programmieren II Klassen. Programmieren II Klassen. Programmieren II Klassen. Zur Erinnerung.

Nun kommt etwas wirklich Abgefahrenes. Wenn Sie zu den Leuten gehören, denen Logikrätsel keinen

Von Java nach C++ Dr. Frank Weichert Lehrstuhl Informatik VII Technische Universität Dortmund

1. Übung zu "Numerik partieller Differentialgleichungen"

C/C++ Programmierung

Von Java nach C++ Frank Weichert, Heinrich Müller Informatik VII Universität Dortmund

Einführung in das Objektorientierte Programmieren mit C++

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2014/2015 Wirtschaftsingenieur Bachelor 4. Aufgabe Datenstruktur, Dateieingabe und -ausgabe

Übung 9. Quellcode Strukturieren Rekursive Datenstrukturen Uebung 9

Klausur zu Objektorientierter Softwareentwicklung in C++ 4. Februar 2003 (WS 2002/2003) Beispiellösung

Grundlagen. Kapitel 1

PIWIN I. Praktische Informatik für Wirtschaftsmathematiker, Ingenieure und Naturwissenschaftler I. Vorlesung 3 SWS WS 2007/2008

Objektorientierte Programmierung mit C++ Zusammenfassung der wichtigsten Topics rund um die objektorientierte Programmierung mit C++11

Praktikum Betriebssysteme 1. Aufgabe (1)

Objektorientierte Programmierung

C++ - Operatoren. Eigene Klassen mit neuen Funktionen

C++-Entwicklung mit Linux

boost::asio-bibliothek 238

Programmierkurs Java

Programmieren in C/C++ und MATLAB

Einführung in die Programmierung

1. Von der Idee zur Software 2. Funktionen und Datenstrukturen Lehrbuch: Organisation des Quellcodes 4. Werte- und Referenzsemantik

Programmieren 3 C++ Prof. Peter Sommerlad Fredy Ulmer

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Praxisorientierte Einführung in C++ Lektion: "Die Compiler-Chain (Vom Quellcode zum ausführbaren Programm)"

Kurzeinführung in C++

Zusammenfassung des Handzettels für Programmieren in C

Java Einführung Methoden in Klassen

Javakurs 2013 Objektorientierung

Die Programmiersprache C

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

C++ für Spieleprogrammierer

10. Klassen. Prof. Dr. Markus Gross Informatik I für D-ITET (WS 03/04)

3 Objektorientierte Konzepte in Java

Klausur in Programmieren

Klausur in Programmieren

Objektorientierung: Klassen und Objekte

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

Angewandte Mathematik und Programmierung

Objective-C CheatSheet

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl

Computeranwendung und Programmierung (CuP)

Programmieren in C++ Arrays, Strings und Zeigerarithmetik

Modellierung und Programmierung

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

Programmierung in C/C++

Probeklausur: Programmierung WS04/05

Informatik I (D-MAVT)

Teil IV. Grundlagen der Programmierung

4. Objektorientierte Programmierung mit C++

Transkript:

Programmieren - C++ Templates Reiner Nitsch 8471 reiner.nitsch@h-da.de

Was sind Funktionstemplates? C++ unterscheidet zwischen Funktionstemplates (dieses Kapitel) und Klassentemplates (später). Funktionstemplates sind Funktionen, die außer einer Werteparameter-Liste in ()-Klammern zur Werteübergabe eine Typparameterliste in <>-Klammern zur Typübergabe haben. So wie zur Laufzeit beim Funktionsaufruf die Aktual-Parameter an Stelle der in der Deklaration benannten Formal-Parameter eingesetzt werden, werden bei Funktions-Templates vom Compiler zur Compilezeit die Aktual-Typen an Stelle der deklarierten Formal-Typparameter eingesetzt. C++ Templates ermöglichen generische Programmierung. Das ist Programmierung unabhängig vom speziellen Objekt-Typ Motivation für Funktionstemplates: Vertauschen von int-, string- oder Fraction-Objekten void swap( int& a, int& b ) int help(a); a = b; b = help; void swap( Fraction& a, Fraction& b ) Fraction help(a); a = b; b = help; Algorithmus ist unabhängig vom Datentyp generischer Algorithmus! Welche Ansprüche stellt der Algorithmus an den Typ 'Fraction'? (Anforderungsprofil) 1) assignable 2) copy-constructable 01.06.2012 C++ Funktions-Templates 2

Funktion swap als Funktionstemplate Deklariert Funktion als Template, das vom Compiler erst bei Bedarf übersetzt wird. Alias T kann auch einfacher Datentyp sein! Auch mehrere Typparameter sind möglich Statt typename kann man auch class schreiben void swap( int& a, int& b ) int help(a); a = b; b = help; Anwendung des Templates swap void main() int a=5, b=6; swap( a, b ); double x=2.0, y=3.0; swap( x, y ); swap( a, x ); swap(a,int(x)); jetzt ok! Compiler erzeugt swap mit Ausprägung int, indem er jedes T durch int ersetzt! template < typename T > void swap( T& a, T& b ) Achtung! T help(a); Copy-Konstruktor Problem wenn T ein und a = b; Zuweisung Klassenobjekt müssen ist? b = help; für Typ T definiert sein! 01.06.2012 C++ Funktions-Templates 3 Typ-Aliase dürfen keine Referenzen oder Pointer sein Compiler erkennt, dass hier T durch int ersetzt werden muss und kompiliert swap(int,int) in Maschinencode. Compiler erkennt, dass hier T durch double ersetzt werden muss und übersetzt swap(double,double) in Maschinencode. Fehler: Deklaration von swap verlangt 2 Parameter gleichen Typs (Kein impliziter Type-Cast bei Templates!)..

Funktionstemplates Zusammenfassung und Einschränkungen Ein Template erlaubt dort EINEN generischen Algorithmus, wo sonst MEHRERE Überladungen desselben Algorithmus notwendig wären. Mit den Templates unterstützt C++ so das KISS-Prinzip. In Funktionstemplates erhält jeder austauschbare Typ einen Zweitnamen (Alias- Name). Sie werden in der Typparameterliste "< >" als solche gekennzeichnet. Bei jedem Aufruf einer Templatefunktion bestimmt der Compiler zunächst durch Deduktion automatisch, welche Typen an den Positionen der austauschbaren Typen aktuell stehen und übersetzt dann den so geänderten Quellcode für diese Ausprägung. Anstelle der automatischen Bestimmung der aktuellen Typausprägung durch den Compiler, kann bzw. muss der Programmierer die Ausprägung auch explizit vorgeben: long a=2, b=3; swap( a,b ); swap<>( a,b ); swap<long>(a,b); template<typename T> T f() //Definition f<int>(); //Aufruf mit expliziter Compiler bestimmt Typausprägung implizit durch Deduktion aus den Typen der Parameter beim Aufruf. Der Programmierer bestimmt hier explizit die gewünschte Typausprägung; eine vom Typ der Parameter abweichende Ausprägung kann nicht erzwungen werden Einschränkung: Typparametrisierte return-werte müssen explizit angegeben werden, weil der Compiler sie nicht deduzieren kann. Aufruf hier nur mit expliziter Ausprägung möglich. Ausprägung für return-type int 01.06.2012 C++ Zeiger 4

Templates: Schnittstelle und Implementierung Bisher galt: Die Schnittstelle einer Klasse oder Bibliothek gehört in eine Header- Datei, die Implementierung in eine cpp-datei. Dieses Prinzip der Trennung von Schnittstelle gilt auch weiterhin. Template-Implementierung muss inkludiert werden! Erklärung: Ein Funktionstemplate ist lediglich eine Bauanleitung für die Schnittstelle und die Implementierung eines Algorithmus. Übersetzt der Compiler eine Projektdatei, die diesen Algorithmus mit einer neuen Typausprägung nutzt, so muss dem Compiler auch die Implementierung des Algorithmus zur erneuten Übersetzung zur Verfügung stehen. Deshalb: Die Implementierung eines Templates gehört in die Headerdatei! // Datei: PG1Lib.h template < typename T > void swap( T& a, T& b ) T help(a); a = b; b = help; 01.06.2012 C++ Zeiger 5

Noch ein Beispiel Mischen von Objekten Generische Funktion zum Erzeugen einer Permutation einer Folge wird gebraucht, wenn der Zufall bei der Programmausführung eine Rolle spielen soll, um gegebene Objekte in eine zufällige Reihenfolge zu bringen. Beispiele: pfirst Zufällige Wiedergabe von Musiktiteln (shuffle mode) Mischen eines Skatspiels plast input void random_shuffle( int* pfirst, int* plast ) int count = plast-pfirst; for( int* pnext=pfirst; pnext!=plast; ++pnext ) ::swap( *pnext, *(pfirst + rand()%count) ); Callback template< typename T > void random_shuffle( T* pfirst, T* plast ) int count = plast-pfirst; for( int* pnext=pfirst; pnext!=plast; ++pnext ) ::swap( *pnext, *(pfirst + rand()%count) ); Implementierung für Ganzzahlfolge (int) Implementierung für bel. Objekttypen. Anforderungen an Objekttypen? 01.06.2012 C++ Zeiger 6

C++ Klassen-Templates Werden auch "parametrisierte Datentypen" genannt Werden oft benutzt, um typanpassbare Container zu realisieren (z.b. in STL) Beispiel: Ein Objekt soll 2 Werte speichern, einen int und einen char Wert class Pair_int_char public: int first; char second; Pair_int_char ( int x, char y ) : first(x), second(y) ; // Beispiel-Anwendung Pair_int_char pair1( 13, 'a' ); cout << pair1.first << endl; cout << pair1.second << endl; Ein anderes Objekt soll ebenfalls 2 Werte speichern, einen bool und einen double Wert class Pair_bool_double public: bool first; double second; Pair_bool_double ( bool x, double y ) : first(x), second(y) ; // Beispiel-Anwendung Pair_bool_double pair2( true, 1.1 ); cout << pair2.first << endl; cout << pair2.second << endl; Mögliche Anwendungen von Containerklassen für 2 Werte: rationale Zahlen, Punkte in einer Ebene, Geldbeträge, Das Beispiel läßt den Wunsch aufkommen, die Klasse pair generisch, d.h. unabhängig von den speziellen Typen zu programmieren und die Typen (ähnlich wie Funktions-Parameter) als Typ- Parameter zu übergeben. 01.06.2012 C++ Templates 7

Realisierung der Pair-Container als Klassen-Template template < typename T1, typename T2 > class Pair public: T1 first; T2 second; Pair( T1 f, T2 s ) first=f; second=s; ; template < typename T1, typename T2 > Pair<T1,T2>::Pair( T1 f, T2 s ) first=f; second=s; Anwendung: Diese Syntax erklärt T1 und T2 zu Typparametern Welche Anforderungen stellt diese Klasse an die Typen T1 und T2? Methoden/Kontruktor-Definition in der Deklaration (Inline-Implementierung) Kritik: Zuerst wird für first und second automatisch der Std-Konstruktor aufgerufen, dann die Objektzustände per Zuweisung korrigiert. Bei Methoden/Kontruktor-Definition außerhalb der Deklaration MÜSSEN zusätzlich zum Klassennamen die Typparameter angegeben werden. Klassentemplates müssen mit expliziter Ausprägung instantiiert werden Pair < int, char > pair3( 13, 'a' ); Pair < bool, double > pair4( true, 0.1 ); // Gleiche Datenstruktur wie pair1! // Gleiche Datenstruktur wie pair2! Auch benutzerdefinierte Typen können als Aktualtyp eingesetzt werden: Pair < Pair_int_char, float > pair7( pair1, 1.234 ); Pair < Pair<int,int>, float > pair8( pair6, 1.234 ); Pair < Fraction*, bool > pair9( &Fraction(2,3), true );

Optimierung der Klasse Pair Verbesserungspotential Der Pair-Konstruktor übernimmt Parameter "by value". Nachteil: Resourcenverschwendung, wenn große Objekte zu übergeben sind. Ausserdem fehlt der Standardkonstruktor. Weshalb? Der Copy-Konstruktor fehlt auch noch template < typename T1, typename T2 > class Pair public: T1 first; T2 second; ; Die STL stellt eine Klasse std::pair<typ1,typ2> mit gleicher Funktionalität bereit. Anwendung siehe Skript 12-1-PG2-STL-Student.pdf 01.06.2012 C++ Templates 9

Statische Containerklasse ArrayForFractions aus Übung 5 class ArrayForFraction public: enum MAX_SIZE = 128 ; private: Fraction elems[max_size]; public: size_t size() const; void fill ( const Fraction& val ); bool empty() const throw(); Fraction& operator[] ( size_t index ); Fraction& at( size_t index ); Fraction& front(); Fraction& back(); Fraction* data() throw(); ; 01.06.2012 C++ Zeiger 10

ArrayForFractions als Klassentemplate Schönheitsfehler: MAX_SIZE ist fest eingestellt! template <typename T, unsigned int MAX_SIZE> C++-Templates bieten auch dafür eine template <typename T> statische Lösung: Auch Werte class ArrayForFraction StaticArray integraler Typen können innerhalb der public: enum MAX_SIZE = 128 ; "<>"Klammern stehen. private: Fraction T elems[max_size]; public: size_t size() const; void fill ( const Fraction& T& val ); bool empty() const throw(); Fraction& T& operator[] ( size_t index ); Anwendung Fraction& T& at( size_t index ); Fraction& T& front(); int main() Fraction& T& back(); Array<Fraction,128> fractions; Array<double,10> doubles; Fraction* T* data() throw(); fractions[0] = Fraction(1,2); ; doubles[0] = 1.2; cout << fractions.size(); bool StaticArray<T,MAX_SIZE>::empty() cout << doubles.size(); return MAX_SIZE==0; return 0; 01.06.2012 C++ Zeiger 11

So, das war s erst mal! 01.06.2012 C++ Zeiger 12

Erzeugung von Zufallszahlen - int rand(void) rand() // gibt pseudo-zufällige Ganzzahl im Bereich [0,RAND_MAX] zurück // Bei wiederholtem Aufruf erhält man eine scheinbar zufällige // Sequenz von Ganzzahlen mit Gleichverteilung. Eine Pseudozufallszahl ist eine Zahl, die zufällig erscheint, in Wirklichkeit jedoch berechenbar ist. Konsequenz: Nach jedem Neustart einer Anwendung liefert rand() die gleiche Sequenz von "Zufallszahlen". Um dieses Verhalten zu ändern, muss man dem Generator bei jedem Systemsstart einen neuen Anfangswert geben. Empfehlung: srand( Initialisiert time(null) den Generator )(default: verwenden, 1) um bei jedem Programmstart einen neuen Anfangswert zu setzen. time ist in <ctime> definiert und liefert die Sekunden seit 1.1.1970. Beispiele: // RAND_MAX (=32767) ist in <cstdlib> definiert rand(); rand(); // liefert 18467 41 srand(2); rand(); rand(); // liefert 29216 45 srand(1); rand(); rand(); // liefert wieder 18467 41 srand( time(null) ); rand() % 100; // liegt im Bereich [0,99] rand() % 100 + 1; // liegt m Bereich [1,100] rand() % 21-10; // liegt im Bereich? [-10,10] 01.06.2012 37

C-Array an Funktion- bzw. Methode übergeben #include <iostream> #include <ctime> #include <cstdlib> //für rand(); srand() using namespace std; double mean ( int array[], int max ); void main() srand(time(0)); const int MAX_N = 1000; int randomnumber[max_n]; for (int i=0; i< MAX_N; i++) randomnumber[i] = rand(); // oder int max = 5; randomnumber[i] = rand() % max; // oder int min = -4; randomnumber[i] = rand() % (max-min)+min; cout << mean(randomnumber, MAX_N) << endl; srand() initialisiert Zufallszahlengenerator; sonst erzeugt rand() nach jedem Programmstart die gleiche Zufallsfolge time(0) liefert Sekunden seit 1.1.1970 liefert gleichwahrscheinliche unsigned int Zufallszahlen im Zahlbereich [0 RAND_MAX] stdlib.h: RAND_MAX 0x7fff (32767) // Bereich [0...max) Die Arraygröße wird i.a. auch // Bereich [min...max) übergeben. Die Funktion kann diese nicht selbst bestimmen. Ein Array wird als Parameter an eine Funktion übergeben durch Angabe des Namens ohne [] 01.06.2012 38