Crashkurs C++ Wiederholung #include <iostream> int main(void) { int i, j; bool is_prime; for (j = 1; j < 1000; j += 2) { is_prime = true; for (i = 3; i <= j/2; i += 2) if (!(j%i)) is_prime = false; if (is_prime) cout << j << endl; C++ ist verwandt zu Java. Zusätzlich gibt es (u. a.): Die Trennung Deklaration/Definition Einen Präprozessor (#-Anweisungen) C++ ist nicht zwingend objektorientiert. Das C++-Hauptprogramm ist die Routine main. Pointer Dagegen fehlen in C++ z. B.: Garbage Collection Exception-Behandlung c 2001 Jens Teubner, Universität Konstanz 1
Deklaration/Definition, Header-Files bibliothek.cc Definition/Implement. bibliothek.h Deklaration bibliothek.o Object File #include "bibliothek.h" int main(void) { //Aufruf der Bibliothek myfunction(42); return 0; programm.cc programm.cc Unser Programm programm.o Object File programm Executable Compiler Linker Deklaration und Definition können getrennt werden. Deklaration üblicherweise in getrennter Datei (Header-Datei mit Endung.h) Dadurch kann von mehreren Quell-Programmen auf einen Programmteil zugegriffen werden. c 2001 Jens Teubner, Universität Konstanz 2
Weiteres zum Präprozessor bibliothek.h // Avoid including this file twice #ifndef BIBLIOTHEK_H #define BIBLIOTHEK_H #define MYMACRO 42 // Function declaration void myfunction(int); #endif bibliothek.cc #include "bibliothek.h" // Function definition void myfunction(int a) {...do something useful... Deklaration und Definition können in C++ getrennt werden. Der Präprozessor macht reines Text- Einfügen/Ersetzen. Dies kann insbesondere mit #define zu unerwünschten Ergebnissen führen (s. Übung) In der Regel darf Code nicht mehrfach eingelesen werden. Absichern mit #ifndef wie im Beispiel #include "datei" sucht im aktuellen Pfad, #include <datei> sucht in den System-Pfaden (für Standard-Bibliotheken). c 2001 Jens Teubner, Universität Konstanz 3
Pointer int a; Var.: bar int &b = a; Typ: int* int *bar; bar = &a; Var.: a / b *bar = 42; // a is now 42 Var.: foo Typ: int struct s baz; Typ: struct s* struct s *foo; foo = &baz; Zeiger "tatsächliche" Variablen Var.: Typ: baz struct s & Deklaration für Ein anderer Name für, erfordert Initialisierung * Deklaration für Pointer auf & Adress-Operator * Inhalt, auf den der Pointer zeigt Ansprechen mit baz.membervar, wenn baz eine echte Variable ist Ansprechen mit foo->membervar, wenn foo ein Pointer auf einen struct ist c 2001 Jens Teubner, Universität Konstanz 4
Anwendung von Pointern In Java sind alle Variablen Pointer Teilweise effizienter, weil weniger Daten im Speicher bewegt werden müssen. Notwendig, wenn Funktionen auf externe Daten zugreifen sollen. Beispiel: Implementation eines Baums struct treeelement { // Our int ; // Pointer to parent element struct treeelement *parent; ; c 2001 Jens Teubner, Universität Konstanz 5
Objektorientiertes Programmieren mit C++ Einführung struct account { // member variables int balance; int limit; // member functions bool deposit(int amount); bool withdraw(int amount); ; bool account::deposit(int amount) {...do something... return true; // successful Objektorientierte Funktionalitäten durch Erweitern der Vorgängersprache C. Ergänzung von Datenstrukturen durch zugehörige Funktionen Interne Datenrepräsentation nach außen nicht sichtbar/irrelevant. Kontrolle der Operationen auf den Daten, z. B. um Unterschreiten des Kontolimits zu unterbinden. Probleme bislang: Zugriff auf Member-Variablen immer noch möglich. Initialisierung der Daten. c 2001 Jens Teubner, Universität Konstanz 6
Zugriffskontrolle, Konstruktor/Destruktor class account { private: int amount; public: account(int); //constructor ~account(void); //destructor bool deposit(int amount); ; account::account(int init_amount) {...do something... account::~account(void) {...clean up... Zugriffskontrolle durch Schlüsselworte private und public (protected) private deklarierte Variablen und Funktionen sind nach außen nicht sichtbar. struct hat public als Standard, class hat private. Konstruktor wird beim Deklarieren eines Objekts aufgerufen. Er kann überladen werden. Der Destruktor wird beim Verlassen des Scope aufgerufen und hat keine Parameter. c 2001 Jens Teubner, Universität Konstanz 7
Nochmal: Header-Files myclass.h class myclass { // This is the private: // definition only! int a; public: int myfunc(int); ; #include "myclass.h" myclass.cc int myclass::myfunc(int foo) { return 42; myprog.cc #include <iostream> #include "myclass.h" int main(void) { myclass myclassvar; cout << myclass.myfunc(42); return 0; So wird kompiliert g++ -Wall -g -c -o myclass.o myclass.cc g++ -Wall -g -c -o myprog.o myprog.cc g++ -Wall -g -o myprog myclass.o myprog.o Die gesamte Klassen-Deklaration kommt in die Header-Datei. Die Definition (d. h. die eigentliche Implementierung) kommt in die.cc-datei. Die Header-Datei kann jetzt von mehreren Programmteilen eingebunden werden. c 2001 Jens Teubner, Universität Konstanz 8
Das Schlüsselwort static void err_msg(char *msg) { static int msgno = 1; cerr << "Error " << msgno++ << ": " << msg << endl; static int foo::bar(void) {...do something... return 42; static float do_something(void) {...do something... static hat mehrere komplett verschiedene Bedeutungen. static-variablen bleiben auch nach Durchlaufen einer Funktion erhalten. Die Initialisierung wird nur einmal durchlaufen. static-member-variablen sind damit vergleichbar. Sie sind nicht an eine Klassen-Instanz gebunden. Für static-member-funktionen gilt das selbe. static-(nicht-member-)funktionen sind nur innerhalb eines Object-Files sichtbar. c 2001 Jens Teubner, Universität Konstanz 9
Das Schlüsselwort const const int abc = 12; class myclass { public: const bar; static const foo = 42; enum { def = 13 ; myclass(int); const int &getptr(int); int getsize(void) const; myclass::myclass(int a) : bar(a) {...do something... Member-Variablen können konstant sein Für die Laufzeit eines Objekts Für alle Instanzen der Klasse Entsprechend unterschiedliche Deklaration/Initialisierung. enum als Trick, um Konstanten zu definieren. const vor Funktionsname heißt Rückgabewert darf nicht links von einer Zuweisung stehen. const nach Funktionsname heißt Funktion darf auch für ein const-objekt verwendet werden. c 2001 Jens Teubner, Universität Konstanz 10
Überladen von Operatoren in C++ C++ bietet noch weitere Möglichkeiten beim Umgang mit Objekten: Die Wirkung von Operatoren wie z. B. +, - auf Objekte kann durch das Überladen von Operatoren verändert/definiert werden, z. B.: complex operator +(complex a, complex b) { return complex( a.real() + b.real(), a.imag() + b.imag() ); Der Copy-Konstruktor für Zuweisung von Klassenvariablen oder beim Funktionsaufruf. complex::complex( const complex &old ) { real_val = old.real_val ; imag_val = old.imag_val; Der automatisch generierte Copy-Konstruktor kopiert einfach alle Member-Variablen. c 2001 Jens Teubner, Universität Konstanz 11