Bedingte Anweisungen Operatoren verknüpfen Variable zu neuen Ausdrücken, wir unterscheiden • Arithmetische Operatoren Berechnung von Werten • Vergleichsoperatoren Überprüfung von Aussagen • Bit Operatoren Manipulation einzelner Bits • Logische Operatoren Verknüpfung von Aussagen Operatoren == != > < >= <= Bedeutung Nicht mit ist gleich ungleich groesser als kleiner als groesser gleich kleiner gleich = verwechseln Es kann innerhalb der if Anweisung eine bool Variable verwendet werden • Syntax bool IFeelGood = true ; if ( IFeelGood ) cout << ”Yeah” << endl ; Bedingte Anweisungen Operatoren verknüpfen Variable zu neuen Ausdrücken, wir unterscheiden • Arithmetische Operatoren Berechnung von Werten • Vergleichsoperatoren Überprüfung von Aussagen • Bit Operatoren Manipulation einzelner Bits • Logische Operatoren Verknüpfung von Aussagen Operatoren Bedeutung && und || oder ! not Innerhalb der if Anweisung können bool Variablen und VergleichsOperatoren verknüpft werden. • Syntax bool IFeelGood = false ; bool RainyDay = true , Cloudy = true ; double SunShineHours = 8.2 ; if ( !RainyDay && (SunShineHours > 8.0 || !Cloudy) ) IfeelGood = true ; Bedingte Anweisungen Operatoren verknüpfen Variable zu neuen Ausdrücken, wir unterscheiden • Arithmetische Operatoren Berechnung von Werten • Vergleichsoperatoren Überprüfung von Aussagen • Bit Operatoren Manipulation einzelner Bits • Logische Operatoren Verknüpfung von Aussagen • Beispiele Operatoren a b true true false false false true true false Möglichkeiten !(a) a && b a || b false true true true false false true false true false false true Zuerst wird der linke Ausdruck überprüft. Ist der true wird der rechte überprüft. Wenn die linke Bedingung falsch ist wird die rechte nicht geprüft. Bedingte Anweisungen Implementieren von Fallunterscheidungen • Wenn … dann .. andernfalls … if( Bedingung ) { Anweisung } else { Anweisung } • Wenn … dann .. andernfalls … Wenn … dann if ( Bedingung ) { Anweisung } elseif ( Bedingung ) { Anweisung } else { Anweisung } In den Anweisungsblöcken können weitere bedingte Anweisungen verwendet werden. if ( Bedingung ) { Anweisung if (Bedingung 2) { Anweisung } } else { Anweisung } Bedingte Anweisungen Alternative Schreibweise, um abhängig vom Wert eines Ausdrucks eine Zuweisung vorzunehmen • Auswahl Operator • Syntax (Zuweisung mit Bedingung) ? Zuweisung wenn true : Beispiel: Minimum von 2 Werten soll zugewiesen werden min = a < b ? a : b Ausführliche Schreibweise if( a<b ){ min = a; } else { min = b; } Zuweisung wenn false Bedingte Anweisungen Alternativ kann die switch Anweisung verwendet werden um Fallunterscheidungen zu implementieren. • Syntax Anweisungsblock wird erreicht, wenn die Bedingung erfüllt ist. switch ( int Variable ) { case integerA : { Anweisungsblock ; break } ….. case integerB : { Anweisungsblock ; break } default: { Anweisungsblock } } wird ausgeführt, wenn nichts zutrifft. Sprung zum Ende von switch. Ohne break werden durch eine einmal erfüllte Bedingung alle folgenden case statements als true durchlaufen! Häufig sieht man statt des Typs int im Kopf von switch auch char. switch ( myChar ) { case 'b' : { cout << “Position B reached“ << endl; break ;} …... default: { cout << “No match found“ << endl;} } Schleifen Wichtiges Element einer Programmiersprache → Wiederholung von Anweisungen • Bearbeiten einer festgelegten Anzahl von Schleifenfolgen for ( Anzahl der Schleifen ) { C++ Anweisungen } Schleifenkopf: Hier wird die Anzahl der Schleifenfolgen kontrolliert und „eigenständig“ gezählt. Anweisungsblock:Hier steht eine Iterationsvariable zur Verfügung • Bearbeiten einer Anzahl von Schleifenfolgen mit Abbruchbedingung while ( Abbruchbedingung ) { C++ Anweisungen } Anweisungsblock: Hier wird die Die Abbruchbedingung wird Abbruchbedingung iteriert. vorher getestet. do { C++ Anweisungen } while (Abbruchbedingung) Anweisungsblock: Hier wird die Abbruchbedingung iteriert. Die Abbruchbedingung wird am Ende getestet. Schleife wird hier mindestens einmal durchlaufen! Schleifen Wichtiges Element einer Programmiersprache → Wiederholung von Anweisungen • Bearbeiten einer festgelegten Anzahl von Schleifenfolgen int j ; const int jmax = 100 ; double a[jmax] ; for (j=0 ; j < jmax ; j++ ){ a[j] = static_cast<double> (j * j) ; } • Bearbeiten einer Anzahl von Schleifenfolgen mit Abbruchbedingung int j = 1 , jmax = 10 ; while (j <= jmax ){ j++; if ( j%7 ) jmax = 13; } int j = 1 , jmax = 0 ; do{ j++; } while ( j <= jmax) ; Arrays Arrays sind Listen von Elementen eines Datentyps. Einzelne Elemente können durch Array Indices angesprochen werden. • Syntax Datentyp Name [Anzahl]; Datentyp Name [N] = {a0, … ,aN-1} ; Überschreitungen des Indexbereiches werden nicht notwendigerweise als Fehler gemeldet. Zufällige Speicherbereiche werden überschrieben! const int maxStunden = 24 ; double Temperatur[maxStunden]={0.}; Temperatur [12] = 22.0 ; Temperatur [24] = 15.0 ; Angabe der Arraylänge Definition und Initialisierung Zuweisung eines Elements Fehler: Arraygrenze überschritten Arrays können auch in mehreren Dimensionen definiert werden • Syntax Datentyp Name [Anzahl][Anzahl]; Zeiger Variable ist ein „Speicherort“ im C++ Programm und hat eine Adresse. - Zugriff auf Variable und/oder Adresse & Variable Adresse * • & Operator liefert die Adresse einer Variablen im Speicher int myVariable = 10 ; &myVariable ; Speicheradresse von myVariable • Zeiger ist eine Variable deren Wert eine Adresse enthält. Zeiger werden im Programm definiert int *pMyInteger; double *pMyDouble ; Type *PointerName ; char *pMyCharacter ; Datentyp eines Zeiger ist für alle Variablentypen eine hex Zahl • Vorsicht beim Deklarieren von pointern int * p1, p2 deklariert eine integer pointer variable und eine integer variable ! Zeiger Variable ist ein „Speicherort“ im C++ Programm und hat eine Adresse. - Zugriff auf Adresse und Variable & Variable Adresse * • * Operator ist eine häufige Anwendung in C++ Programmen und hat zwei unterschiedliche Bedeutungen - Pointer Variablen Definition mit Typ Angabe - Dereferenz Operator im Quellcode in Form von value pointed to by (Wert auf den gezeigt wird) • * Operator als Dereferenz im code int MyVariableA = 10 ; int *pMyVariableA ; int MyVariableB ; pMyVariableA = &MyVariableA ; Adresse der Variablen MyVariableA MyVariableB = *pMyVariableA ; Wert auf den gezeigt wird MyVariableB ist jetzt 10 Zeiger • Zuweisungen und Rechnen mit Zeigern & Variable int MyVariableA = 10 ; int MyVariableB = 20 ; int *pMyVariableA , *pMyVariableB ; Adresse * pMyVariableA = &MyVariableA ; pMyVariableB = &MyVariableB ; Value pointed to by pMyVariableA wird auf 100 gesetzt Value pointed to by pMyVariableB = *pMyVariableA = *pMyVariableB; value pointed to by pMyVariableA *pMyVariableA = 100; pMyVariableA = pMyVariableB; A und B haben die gleichen pointer *pMyVariableA = 200 ; Value pointed to by pMyVariableA = 200 Zeiger und Arrays • In der Deklaration einer array Variablen ist der array Name der Zeiger auf das erste array Element const int nLength = 50 ; double MyArray [nLength] ; MyArray is equivalent to &MyArray[0] double *pMyArray ; pMyArray = MyArray ; *pMyArray = 500; pMyArray++ ; *pMyArray = 1000; pMyArray = MyArray + 2; *pMyArray = 3000; pMyArray = MyArray; *(pMyArray + 3) = 2; MyArray[4] = 10000; wird häufig so verwendet setzt das erste array Element auf 500 läuft durch die array Elemente setzt das zweite array Element auf 1000 setzt den pointer auf Element 2 setzt das dritte array Element auf 3000 setzt den pointer auf Element 0 setzt das vierte array Element auf 2 setzt das fünfte array Element auf 10000 Zeiger und Arrays • Komplexe Zeiger Konstruktionen Das Zeigerkonstrukt wird von innen nach aussen aufgelöst. int n = 50 , m = 100 ; int *nptr; int **npptr; int *ptrArray[2]; nptr = &n ; npptr = &nptr ; ptrArray[0] = &n; ptrArray[1] = &m; …... **(&ptrArray[0]) **npptr …... int Zeiger Zeiger auf einen int Zeiger Array von int Zeigern Adresse von n Adresse vom Zeiger auf n Adressen von m und n = 50 = 50 Dynamischer Speicher const int maxTage = 24 * n ; Fehler: Arraygrenze dynamisch double Temperatur[maxTage]={0.}; Mit den C++ Operatoren new und delete lässt sich dynamisch (während der Laufzeit des Programmes) Speicher allokieren. Die Operatoren können auf beliebige Objekte angewandt werden. • Syntax Datentyp * Name = delete [] Name ; new Datentyp [ Anzahl ]; Bei jeder Verwendung von new sollte man überlegen wie der Speicher wieder freigegeben werden soll. …... Erzeugung eines Arrays mit einer Länge, die int N , K , J; während der Laufzeit im Programm festgelegt wird. …... Erzeugung des Arrays mit N = K*J ; double* DynamicArray = new double [N]; N Elementen DynamicArray[K+1] = (double) ((K+1)*(K+1)); Verwendung wie jedes Array …….. delete [] DynamicArray; Speicherfreigabe Input / Output in Files Ein Spezialfall des Schreibens in / Lesens von Files wurde mit den Befehlen cin und cout behandelt. Es lassen sich allgemeinere Ein- und Ausgabeströme öffnen, die dann ein Schreiben in Dateien erlauben. • Syntax #include iostream Einfügen der header files #include fstream …….. ifstream inFile ( InputFileName ); Öffnen eines Input und Output ofstream outFile ( OutputFileName );Stroms if (inFile.is_open()) { War das Öffnen erfolgreich Lesen bis while ( inFile >> myInteger >> myDouble ) File Ende { myInteger *= 10 ; } inFile.clear(); Reset ifstream, z.B. um File erneut zu lesen inFile.seekg(0,ios::beg); Setzen der Fileposition auf Filebeginn inFile.close(); Schliessen des Files Jetzt könnte das File } erneut gelesen werden! else { Fehler behandlung cerr << “Can not open file“ << InputFileName <<endl; } Input / Output in Files Mit den Ein und Ausgabeströmen sind Zustandsbeschreibungen verknüpft, die verwendet werden können. ifstream inFile ( InputFileName ); …... inFile.bad(); inFile.good(); true, wenn das File Ende erreicht wurde inFile.eof(); inFile.clear(); Reset der obigen Flags, wird beim erneuten Lesen benötigt …... while ( !inFile.eof() ){ Ausführung bis zum Ende } …….. Die Positionierung im geöffneten File lässt sich steuern inFile.seekg(0,ios::beg); inFile.seekg(0,ios::end); Die Dokumentation enthält weitere Funktionen. Positionierung relativ zum Filebeginn oder zum Fileende. Der 1. Parameter ist der Offset. Input / Output in Files Mit Hilfe von Funktionen können Text Files gelesen werden. #include <iostream> #include <fstream> #include <string> ……... string TextZeile; ifstream inFile (“BeispielTextFile.txt“); if (inFile.is_open()) { while ( getline ( inFile , TextZeile ) ) { cout << TextZeile << endl; } inFile.close(); } else { Cerr <<“Fehler, File kann nicht geoeffnet werden “ << endl; } Input / Output in Files Das folgende Beispiel zeigt noch einmal die wichtigsten C++ Anweisungen, die für den lesenden und schreibenden Zugriff auf Files gebraucht werden. #include <iostream> Definitionen für die #include <fstream> Input/Output Klassen int main { …. Output File Name char Filename[] = “myFile.txt“; ofstream outFile ( Filename ); Pointer für Output Stream Schreiben von 2 Variablen outFile << myVarA << myVarB ; } ifstream inFile ( Filename ); inFile >> myVarA >> myVarB ; Schliessen des Output Stream …. outFile.close(); inFile.close(); readFile.cc Arbeitsvorschlag: - Schreiben Sie ein Programm, das in ein File schreibt bzw. liest. Funktionen Zum Strukturieren komplexerer Programme werden funktionale Einheiten ausgelagert. • Syntax returnType FunctionName (ParameterList) { falls Rückgabewert C++ Anweisungen void oder Parameter leer } - Funktionen stehen meistens hinter dem „Hauptprogramm“ int main() { Dabei ist die Reihenfolge nicht von Bedeutung. - Sie werden vor dem Hauptprogramm deklariert returnType FunctionName (ParameterList); Die Parameterliste muss nur die Typ Deklaration enthalten - Die Funktionsdeklarationen werden häufig in Files mit der Endung .h ausgelagert. Das Einfügen erfolgt erfolgt mit #include “myHeader.h“ } Funktionen – Ein Beispiel • Beispiel int max ( int N , int M ) { int result ; if ( N > M ) result = N ; else result = M ; return result ; } Rückgabe des Maximums 2er Zahlen Parametertyp deklarieren Funktionstyp deklarieren int max ( int , int); steht vor dem main Programm Lokale Variable, nur in der Funktion bekannt Rückgabewert Parameter Liste enthält nur die Typ Deklaration Funktionen – Ein Beispiel • Beispiel int max ( int N , int M ) { int result ; if ( N > M ) result = N ; else result = M ; return result ; } Rückgabe des Maximums 2er Zahlen Parametertyp deklarieren Funktionstyp deklarieren Lokale Variable, nur in der Funktion bekannt Rückgabewert int max ( int , int); steht vor dem main Programm Arbeitsvorschlag: functionSum.cc - Schreiben Sie ein Programm, das in einer Funktion 2 Zahlen summiert. - Erzeugen Sie eine header Datei mit der Funktionsdeklaration und binden Sie sie ein. - Lagern Sie die header Datei in ein include dir aus. Mit der Compiler Option -I dir koennen Sie das directory einbinden Funktionen - Parameterübergabe Beim Übergeben der Funktionsargumente ist zu beachten, das die Speicherbereiche beim Aufruf der Funktion erzeugt werden und beim Verlassen der Funktion nicht mehr existieren! • Methoden zur Übergabe von Funktionsparametern - Call by value (default) double function (int A, int B) { } A und B werden beim Funktionsaufruf kopiert und Änderungen innerhalb der Funktion haben keinen Effekt auf die Werte A und B im Hauptprogramm - Call by reference double function (int &A, int &B) { } Die Adressen von A und B werden beim Funktionsaufruf übergeben und Änderungen der Adressinhalte innerhalb der Funktion beeinflussen die Werte A und B im Hauptprogramm void swap( int &N , int &K ){ int temp; temp = N; N = K; K = temp; return ; functionSwap_I.cc } functionSwap_II.cc Alternativ können auch pointer übergeben werden Funktionen - Parameterübergabe Arrays werden häufig an die Funktionen als Zeiger übergegeben. Dabei wird die Arraylänge als konstanter Wert ebenfalls übergegeben. addArray.cc Der Inhalt von Array ValC wird in der Funktion sum modifiziert. Die Werte werden by Reference zurückgegeben, Daher sind die Änderungen sichtbar. Funktionen – statische Variablen Die lokalen Variablen von Funktionen existieren nur für die Lebensdauer der Funktion. Zugewiesene Werte existieren nach dem Aufruf nicht mehr. • Statische Variable static Datentyp Name ; Diese Anweisung definiert eine Variable, deren Inhalt nach dem Schliessen der Funktion erhalten bleibt und bei erneutem Aufruf zur Verfügung steht. • Globale Variable Datentyp myGlobalVariable ; ….. void function(){ } main() { ….. } Variablen, die ausserhalb von Funktionen und vor dem Hauptprogramm definiert werden, stehen in allen Funktionen zur Verfügung und behalten ebenfalls den Inhalt nach dem Schliessen der Funktionen. Überladen von Funktionen Wenn verschiedene Funktionen unter dem gleichen Namen angesprochen werden können, sprechen wir von überladenen Funktionen. Dabei ist nur eine Änderung der Anzahl der Parameter in der Parameterliste oder der Parametertypen zulässig. double multiply (int a , int b){ return (double) (a*b) ; } double multiply (double a , double b){ return a*b ; } double multiply (int a , int b , int c) { return (double) (a*b*c) ; } double multiply (double a , int b , int c) { return a * (double)(b*c) ; } Rekursive Funktionen Der Selbstaufruf von Funktionen wird als Rekursion bezeichnet. Eine Abbruchbedingung sorgt dabei für eine endliche Anzahl von Aufrufen. • Bei einer rekursiven Lösung wird ein Problem immer wieder schrittweise in ein einfacheres Problem verwandelt. • Rekursive Programme können fast immer auch iterativ implementiert werden. Meist führt das jedoch zu komplizierterem Code. Rekursive Lösungen sind in der Regel rechenzeit- und speicherintensiver. Inline Funktionen Der Aufruf von Funktionen wird durch das Schlüsselwort inline verändert. Der Programmcode wird durch den Compiler direkt in das Programm eingefügt. inline returnType myFunction( ParameterList ) { C++ code ; } Diese Anweisung ist für den Compiler nicht bindend. Typischerweise werden nur kurze Funktionen direkt eingefügt. Funktionen – Eingabe Parameter Der Funktion main() können auch Parameter übergeben werden. Die vollint main(int argc , char *argv[]) ständige Definition ist Dabei gibt argc die Anzahl der Argumente an; im vector argv[] stehen Pointer auf die übergebenen Parameter. In argv[0] steht dabei immer der Programmname. Hilfsfunktionen zum entpacken der Parameter stehen über die Standard Bibliotheken zur Verfügung. #include <stdio.h> readOptions.cc int main(int argc, char *argv[]) { for(int i=0; i < argc; i++) { printf("argv[%d] = %s ",i,argv[i]); printf("\n"); } return 0; } testOptions.cc Komplexere Beispiele finden Sie hier adderOptions.cc Funktionen - Bibliotheken Funktionen können in Bibliotheken als Objektfiles sowohl statisch (.a) als auch dynamisch (.so) gespeichert werden. • Erzeugen einer statischen Bibliothek Der Quellcode ist die function myFunc.cc und die header Datei myFunc.h - compilieren der Quelldateien und erzeugen des Objektfiles gcc -c myFunc.cc -o myFunc.o - verwenden der archiver ar zur Erzeugung der statischen Bibliothek ar rcs libmyFunc.a myFunc.o Der Bibliotheksname muss die ersten 3 Buchstaben lib enthalten und mit .a enden. Im link Schritt von gcc muss -static hinzugefuegt werden. • Erzeugen einer dynamisch gelinkten Bibliothek - compilieren der Quelldateien und erzeugen des Objektfiles gcc -fPIC -c myFunc.cc -o myFunc.o Die Option -fPIC erzeugt positionsunabhaengigen code - verwenden von gcc zur Erzeugung der dynamischen Bibliothek gcc -shared -Wl,-soname,libmyFunc.so -o libmyFunc.so myFunc.o - beim link Schritt in gcc zum Einbinden der dynamischen Bibliothek reicht die Endung .so der Bibliothek g++ myProg.cc -L. -lmyFunc Funktionen – Werkzeug Bibliotheken Es existiert eine C++ Bibliothek, die standardisierte Werkzeugprogramme enthält (C++ Standard Library). Die C Bibliothek ist darin enthalten. • Standard Funktionen aus den Bereichen Mathematische Funktionen, Input / Output, Zeichenketten, Zeit / Datum, Speichermanipulation, ….... Erzeugung von Zufallszahlen: #include <cmath> #include <cstdlib> ….. #include <ctime> double t, x; ….. x = sin(t); // initialize with time x = log(t); srand(time(0)); x = exp(t); // random integer x = sqrt(t); int r = rand(); ….. ….. • Objektorientierte Klassenbibliothek Klassendefinitionen für Input/Output, Strings, Standard Template, Container, Iteratoren, Fehlerbehandlung, ….... Die C++ Standard Library wird im g++ Link Schritt automatisch hinzugefügt. Funktionen – Werkzeug Bibliotheken (2) Die C++ Standard Library wird bei der Verwendung des g++ Compilers im Link Schritt automatisch hinzugefügt. Neben der C++ Standard Library gibt es viele kommerzielle und public domain Bibliotheken mit spezieller Funktionalität. Vor dem Programmieren einer speziellen Softwarelösung sollten existierende Bibliotheken durchgesehen werden. • Bibliotheken - Beispiele boost OpenMP cuda freie C++ Bibliothek (mathematische Lösungen, …..) Paralleles Computing Programmieren auf Nvidia Graphikkarten • Verwendung von Bibliotheken - Hinzufügen des header files im Programmcode #include <boost/random.hpp> - Aufrufen der Funktion im Hauptprogramm gen() - Hinzufügen der Bibliothek im Link Schritt des Compilers g++ myCode.cc -L/usr/lib64/boost/ -lboost_random (/usr/lib64/boost/libboost_random.so wird hinzugefügt) Funktions-Templates C++ beinhaltet Möglichkeiten zur generischen Programmierung. Ein Funktions-Template verhält sich wie eine Funktion, die Argumente verschiedener Typ Definitionen bzw Rückgabe Wert Typen akzeptiert. Die Funktionen enthalten dazu Platzhalter Typ Definitionen. Platzhalter Typ Definition Angabe des verwendeten Typs funcTemplate.cc Funktionen – Werkzeug Bibliotheken Standard C++ library ist eine Programmierbibliothek, die auch die C Bibliotheken enthält. • Beispiel Container – vector class vector ist eine container class, die dynamische arrays implementiert #include <vector> Intialisieren von vector ….. vector <int> myVector; vector <int> p; vector <double> yourVector(10,5.0) Hinzufügen eines Elements int iElem = 10 ; am Ende von myVector myVector.push_back(iElem); Löschen des letzten myVector.push_back(74); Elements von myVector myVector.pop_back(); int myVectorSize = myVector.size(); for(int i=0;i<yourVector.size();i++) Grösse von myVector cout << “Elem “<<i<<“ is “ << yourVector[i]<< endl; ….. Schleife über alle Elemente von yourVector Beispiel Vector Class readFile_0.cc Filename des Text Files Öffnen des Files Schleife über alle Einträge des Files Schliessen des Files Strings Statt Zeichenketten in ein char array zu schreiben lässt sich auch die Standard Library Klasse string verwenden. Eine explizite Angabe der Länge der Zeichenkette ist hier nicht notwendig. • Syntax und einige wichtige Funktionen Deklaration der string Variablen #include <string> Strings lassen sich durch addieren …... aneinander hängen string myStrA = “Warum“ , myString ; string myStrB = “ auch das noch“ myString = myStrA + myStrB; cout << myString << endl; → Warum auch das noch …... Länge eines strings int nLength = myString.length(); → nLength = 19 pos = myStrA.find(“um“); → pos = 3 Finden eines sub strings myStrA.insert(5,“ nicht“); → Warum nicht Einfügen / myStrB.erase(5,9); → auch löschen eines sub strings myStrA.c_str(); Gibt eine nicht-modifizierbare Standard C Zeichenarray Version der Zeichenfolge zurück Viele Verbesserungen in C++11 Klassen – Einleitung Ziel von C++ ist der Support objektorientierter Programmierung (OOP). Dabei handelt es sich um ein Konzept zur Strukturierung von Programmen bei dem Programmlogik (Funktionalität) und Programmzustand (Datenstrukturen) vereinigt werden. Die Vereinigung wird Objekt genannt. • Objekte werden im Programm erzeugt und vernichtet. • Objekte haben zur Laufzeit des Programms definierte Zustände • OOP erlaubt die Kommunikation zwischen Objekten OOP wird in C++ mit Hilfe von Klassen realisiert. Sie vereinigen Datenstrukturen und Funktionen zur Veränderung der Daten. • Anschaulich: Klassen sind Vorlagen und Konstruktionspläne aus denen zur Laufzeit Objekte erzeugt werden (Instanzen). • Alorithmen die auf den Datenstrukturen von Klassen operieren heißen Methoden • Klassen kapseln zusammengehörige Daten und Funktionen und unterstützen Datenzugriff nur über spezielle Funktionen. Methoden die Objekte erzeugen oder zerstören werden als Konstruktoren oder Destruktoren bezeichnet. Klassen – ein Beispiel Ziel von C++ ist der Support von OOP. Dabei spielen Klassen eine wichtige Rolle. Sie vereinigen Datenstrukturen und Methoden zur Änderung der Daten. • Betrachte ein Beispiel: Klasse von Vierervektoren zur Beschreibung von Vierervektor: Teilchenreaktionen class FourVector { Klassenname, identifiziert die Klasse public: Definiere Funktionen, die die Elemente des Vektors füllen Definiere Funktionen, die den Impuls, Energie und invariante Masse zurückgeben. Klassenmitglieder - Datenstrukturen - Funktionen/Methoden private: definiere Daten, die zum Vektor gehören } vect ; int main(){ FourVector Elektron, Proton; ….. Optional Objektnamen Erzeuge Instanzen von FourVector Klassen – ein Beispiel Ziel von C++ ist der Support von OOP. Dabei spielen Klassen eine wichtige Rolle. Sie vereinigen Datenstrukturen und Methoden zur Änderung der Daten. • Betrachte ein Beispiel: Klasse von Vierervektoren zur Beschreibung von Teilchenreaktionen Zugriffsrechte werde explizit mit Hilfe class FourVector von Schlüsselwörtern gewährt { Auf alle Klassenmitglieder die hier stehen gibt es nur von Mitgliedern Zugriff public: Diese Klassenmitglieder können vom gesamten Programm benutzt werden private: Nur Mitgliedern ist der Zugriff erlaubt }; int main(){ FourVector Elektron, Proton; ….. Klassen – ein Beispiel • Betrachte ein Beispiel: Klasse von Vierervektoren zur Beschreibung von Teilchenreaktionen Methoden erlauben Zugriff auf die class FourVector{ Datenstruktur. public: void setE(double e) {E = e;} void setP(double x, double y, double z){ px = x; py = y ; pz = z;} double getE(void)const {return E;} double getP(void)const { return sqrt(px*px+py*py+pz*pz);} FourVectorClass_0.cc private: double E, px, py, pz; } ; Datenstruktur ist nicht zugänglich int main(){ FourVector Elektron, Proton; Elektron.setE(100.); Proton.setP(10., 20., 50.); Proton.getP(); return 0 ;} Zwei Instanzen von FourVector werden erzeugt. Mit dem Punkt Operator werden die Methoden erreicht. Klassen – ein Beispiel • Betrachte ein Beispiel: Klasse von Vierervektoren zur Beschreibung von Teilchenreaktionen Klassendefinition werden im Header class FourVector{ File untergebracht. public: void setE(double e); void setP(double x, double y, double z); double getE(void)const; Die Methoden können auch double getP(void)const; ausserhalb der Klassendefinition private: definiert werden. Auf die Klasse double E, px, py, pz; wird mit Klassenname:: bezug } ; genommen. FourVector::setE(double e){ E = e; Scope operator } double FourVector::getE(void)const{ return E; } ……. FourVectorClass_I.cc Klassen – ein Beispiel • Konstruktor und Destruktor einer Klasse Konstruktor, code wird bei der Instanzierung gerufen class FourVector{ public: FourVector(void){ E=0.;px=0.;py=0.;pz=0.} ~FourVector(void) { } Destruktor void setE(double e) {E = e;} void setP(double x, double y, double z){ px = x; py = y ; pz = z;} double getE(void) {return E;} double getP(void) {return sqrt(px*px+py*py+pz*pz);} private: double E, px, py, pz; } ; int main(){ FourVector Elektron, Proton; Zwei Instanzen von FourVector werden erzeugt. Beide sind durch den Konstruktor initialisiert. Klassen – ein Beispiel • Konstruktor einer Klasse - Kein Rückgabetyp, Argumente können void oder eine Variableliste sein - Konstruktor hat den Namen der Klasse und dient der Initialisierung des Objektes class FourVector{ Public: FourVector(double e,double x,double y, double z); FourVector(); …. Private: double E, px, py, pz; Initialisierung der Variablen }; FourVector::FourVector(double e,double x,double y, double z): E(e),Px(x),Py(y),Pz(z){} Synthax FourVector::FourVector(){ E=0.; px=0.; py=0.; pz=0.} …….. FourVector Pion; FourVector Kaon(5.,1.0,1.5,19.); Zuweisung der Variablen, um zu initialisieren Initialisierung von array geht nur über Zuweisung ! Klassen – ein Beispiel • Konstruktor einer Klasse - Im Header können Default Parameter angegeben werden. - Konstruktor kann ueberladen werden - Kopierkonstruktur wird vom System erzeugt, erstellt ein Objekt der Klasse anhand eines vorhandenen Objektes. Der Parameter ist immer eine Referenz auf ein konstantes Objekt der selben Klasse. class FourVector{ Public: ~FourVector(){}; Destruktor FourVector(double e=0.,double x,double y, double z); FourVector(FourVector const& FourVectorObjekt); …. Private: double E, px, py, pz; }; • Destruktor einer Klasse - Einer pro Klasse - Ist fuer Aufräumarbeiten zuständig Klassen – ein Beispiel • Eine Klasse wird instanziert, indem die Klassenbezeichnung und ein Name angegeben wird. Der Zugriff auf Member Funktionen und Variablen erfolgt über den Operator „ . “ Für Pointer auf Klassen wird der Operator „ → “ verwendet. Er besorgt die Dereferenzierung und den Memberzugriff. class FourVector { …. } int main() { FourVector Kaon; FourVector *Pion; ….. Kaon.setE(20.); ….. Pion->GetMomentum(); …... } this Zeiger • this Pointer einer Klasse Jede nicht statische Methode hat eine versteckte Zeigervariable, in der die Adresse des Objektes gespeichert wird, die die Methode aufgerufen hat. this ist ein C++ Schlüsselwort. Die “interne“ Deklaration kann man sich so vorstellen: myClass * const this = &object; Der this Zeiger wird benutzt wenn eine Adresse der eigenen Klasse zurückgegeben wird. In vielen Fällen wird this automatisch ergänzt. In nicht eindeutigen Fällen z.B. lokale Variablen heissen wie die Klassen Variablen, sollte this hinzugefügt werden. class FourVector { ……. FourVector & FourVector::compare (FourVector & v){ If ( condition ) return v ; // v ist Argument else return *this ; // aufrufendes Objekt } Operatoren • Operatoren in Klassen Klassen definieren neue Typen, die in C++ genutzt werden. Typ Definitionen werden aber nicht nur in Form von Konstrukten und Zuweisungen verwendet, sondern müssen auch Operatoren (z.B + - ..) verstehen. class FourVector{ double E, px, py, pz; public: FourVector(){ E=0.;px=0.;py=0.;pz=0.} void setE(double e) {this->E = e;}Erlaubt das Summieren von zwei Instanzen von FourVector ….. double getP(void){return sqrt(Px*Px+Py*Py+Pz*Pz);} FourVector operator+(const FourVector& v) { FourVector vec; vec.E=this→E+v.E; vec.Px=this→vec.Px + v.Px; vec.Py=this→Py+v.Py; vec.Pz=this->Pz+v.Pz; return vec; Das Schlüsselwort this ist ein } pointer auf das aktuell benutzte ……. Objekt. Vererbung Klassen können die Implementierung (Methoden und Variablen) von einer anderen Klasse übernehmen (Vererbung). Altes Verhalten kann umgeändert und neues hinzugefügt werden, die grundlegende Schnittstellen bleiben jedoch gleich (Polymorphie). Das Ableiten einer neuen Klasse (Sub- oder Unterklasse) von einer bereits bestehenden (Ober- oder Basis-) Klasse wird folgendermaßen erreicht: class BaseClass { ….. }; class SubClass: ZugriffsOperator BaseClass { ….. public In SubClass stehen fast alle member }; von BaseClass zur Verfügung private Alle member von BaseClass sind privat protected Alle member von BaseClass sind protected • Zugriffskontrolle auf die BaseClass Variablen von SubClass aus Variable im private Bereich können von SubClass aus nicht erreicht werden. Lösung: verschiebe private BaseClass Variable in protected Vererbung Beispiel mit unserer FourVector Klasse, die als Basis Klasse die ThreeVector Klasse hat : class ThreeVector { double Px,Py,Pz; public: ThreeVector(double x, double y, double z): Px(x),Py(y),Pz(z){} ……. }; class FourVector: public ThreeVector { double E ; public: FourVector(double e, double x, double y, double z): E(e), ThreeVector(x,y,z) {} ……. }; inherit.cc Funktionen - Overloading Funktionen können gleichzeitig mit den selben Namen definiert werden, wenn Sie eine unterschiedliche Anzahl von Parametern besitzen oder die Parameter von unterschiedlichem Typ sind. • Overloading overloading.cc ….... class stdOutputData { public: void print(int j){cout << "Write integer: " << j << endl;} void print(double x){cout << "Write double: " << x << endl;} void print(char* c){cout << "Write character: " << c << endl;} }; …... stdOutputData p; int k = 5 ; double f = 2.3 ; char c[256] = "Hi there" ; // Write print to print integer , float or character p.print(k); p.print(f); p.print(c); …..