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

22
DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 Algorithm Engineering Fakultät für Informatik, TU Dortmund

Transcript of DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung...

Page 1: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

DAP2-ProgrammierpraktikumEinführung in C++ (Teil 2)

Carsten Gutwenger18. April 2008

Lehrstuhl 11 – Algorithm EngineeringFakultät für Informatik, TU Dortmund

Page 2: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 2

Überblick

• Dynamischer Speicher

• Klassen und Strukturen

– Const-Korrektheit

– Virtuelle Funktionen

• Überladen von Operatoren

• Generische Programmierung

Page 3: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 3

Dynamischer Speicher

Zwei Arten von Speicher

• Stack

– lokale Variablen, Funktionsparameter

– Lebensdauer: bis Funktionsende

• Heap– dynamisch angefordert mit new

– Lebensdauer: bis Aufruf von delete

Page 4: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 4

Einfaches Beispiel

struct Pair { int x, y };

Pair *createPair() {

Pair *p = new Pair;

p->x = 17; p->y = 4;

return p;

}

void usePair() {

Pair *q = createPair();

cout << "pair is " << q->x << ", " << q->y << endl;

delete q;

}

Speicher für Pair auf Heap anlegen

Speicher für Pair auf Heap wieder freigeben

Page 5: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 5

Beispiel mit Feldern

int *createArray(int n) {

int *a = new int[n];

for(int i = 0; i < n; ++i)

a[i] = i;

return a;

}

void useArray() {

int *a = createArray(100);

for(int i = 0; i < 100; ++i)

cout << "a[" << i << "] = " << a[i] << endl;

delete [] a;

}

new-Operator für Felder

delete-Operator für Felder

Page 6: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 6

Zusammenfassung

• Dynamischer Speicher wird mit new angelegt und mit deletewieder freigegeben.

• Beim Anlegen eines Objektes können auch Parameter an den Konstruktor übergeben werden:– Pair *p = new Pair(x,y);

• Dynamische Felder– Werden mit der Array-Form des new-Operators angelegt.

– Müssen mit der Array-Form des delete-Operators freigegeben werden.

– Für Elemente wird immer der Default-Konstruktor aufgerufen.

Page 7: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 7

Klassen und Strukturen

struct A {

int x; // public

private:

int y;

};

class A {

int x; // private

public:

int y;

};

Default-Sichtbarkeit:

• struct: public

• class: private

Page 8: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 8

Wichtige Member-Funktionen

• Konstruktoren:– Default-Konstruktor: Pair();

– Copy-Konstruktor: Pair(const Pair &x);

– weitere: Pair(int x, int y);

• Destruktor:– Wird vor dem Freigeben des Speichers für das Objekt aufgerufen

– ~Pair();

• Operatoren (z.B. Zuweisungsoperator)– später!

• Achtung: Werden teilweise automatisch erstellt!– Default- und Copy-Konstruktor, Zuweisungsoperator

Page 9: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 9

Erzeugen von Objekten einer Klasse

• Merke: Klassen sind vollwertige Datentypen und können wie primitive Datentypen verwendet werden!– Keine Notwendigkeit für new, wenn nur eine lokale Variable benötigt

wird; dann braucht man sich auch nicht um delete zu kümmern.

class Pair { ... };

Pair a; // Default-Konstruktor

Pair b(22,33); // selbst-definierter Konstruktor

Pair c(a); // Copy-Konstruktor

Pair *d = new Pair(b); // Copy-Konstruktor

...

delete d; // nicht vergessen!

Page 10: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 10

Statische Methoden

• Methoden, die nicht mit einer Instanz assoziiert sind.– kein Zugriff auf nicht-statische Member

class A {

static int counter;

public:

static void f(int i);

};

int A::counter = 0;

void A::f(int i) {

counter += i;

}

Deklaration

Definition

Page 11: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 11

Const-Korrektheit

• Von Konstanten und Const-Referenzen dürfen nur Methoden aufgerufen werden, die mit const deklariert sind.– Diese Methoden dürfen keine Member-Variablen ändern

class Pair { Pair a(1,2);

int x, y; const Pair b(3,4);

public: const Pair &c = a;

Pair(int a, int b)

: x(a), y(a) { } int xa = a.getX(); // ok

int getX() const { int xb = b.getX(); // ok

return x; int xc = c.getX(); // ok

} a.incX(); // ok

void incX() { ++x; } b.incX(); // Fehler!

}; c.incX(); // Fehler!

Page 12: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 12

Vererbung

• Klassen und Strukturen können von Basisklassen erben.– Spezifikation der Sichtbarkeit: public, protected, private

– mehrere Basisklassen erlaubt

• Dynamisches Binden bei Methoden– Diese Methoden müssen explizit als virtuell deklariert werden.

– „pure virtual“ Methoden definieren nur Schnittstellen und müssen in abgeleiteten Klassen implementiert werden.

• Klassen mit virtuellen Methoden sollten auch einen virtuellen Destruktor besitzen.

Page 13: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 13

Beispiel zur Vererbung

class Figure {

public:

virtual void draw() = 0; // pure virtual

};

class Circle : public Figure {

public:

void draw(); // virtuell, da virtuell in Basisklasse

};

void Circle::draw() {

...

}

Page 14: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 14

Überladen von Operatoren

• Operatoren können quasi wie ganz normale Funktionen deklariert werden.– Schreibweise z.B. für Vergleichsoperator: operator==

– Im Prinzip können alle Operatoren überladen werden.

– Operatoren können als Methoden in Klassen oder globale Funktionen definiert werden.

• Beispiel (globale Funktion):

bool operator==(const Pair &a, const Pair &b) {

return (a.getX() == b.getX()) &&

(a.getY() == b.getY());

}

Page 15: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 15

Überladen von Operatoren (2)

class Pair {

int x, y;

public:

Pair() : x(0), y(0) { }

Pair(int a, int b) : x(a), y(b) { }

Pair(const Pair &p) : x(p.x), y(p.y) { }

Pair &operator=(const Pair &p);

Pair operator+(const Pair &p);

Pair &operator+=(const Pair &p);

};

ostream &operator<<(ostream &os, const Pair &p);

Page 16: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 16

Überladen von Operatoren (3)

Pair & Pair::operator=(const Pair &p) {

x = p.x; y = p.y;

return *this; // gibt Referenz auf aktuelles

} // Element zurück

Pair Pair::operator+(const Pair &p) {

return Pair(x+p.x,y+p.y);

}

Pair &Pair::operator+=(const Pair &p) {

x += p.x;

y += p.y;

return *this;

}

Page 17: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 17

Überladen von Operatoren (4)

ostream &operator<<(ostream &os, const Pair &p) {

os << "(" << p.getX() << "," << p.getY() << ")";

return os;

}

• ostream ist Basisklasse für Ausgabestreams– cout ist ein Ausgabestream– ofstream: Klasse für Ausgabe in Dateien

• Warum wird eine ostream-Referenz zurückgegeben?– cout << x << y << z << endl;

– << ist linksassoziativ:((((cout << x) << y) << z) << endl;

Page 18: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 18

Generische Programmierung

• Viele Funktionen können für eine Vielzahl von Datentypen definiert werden und sehen nahezu identisch aus:– short abs(short x) { return (x<0) ? -x : x; }

– int abs(int x) { return (x<0) ? -x : x; }

– float abs(float x) { return (x<0) ? -x : x; }

– double abs(double x) { return (x<0) ? -x : x; }

• Geht das nicht einfacher?– template<typename T>

T abs(T x) { return (x<0) ? -x : x; }

– Kann für jeden Datentyp T benutzt werden, der einen Kleiner-Operator, ein unäres Minus, einen Konstruktor für 0 und einen Copy-Konstruktorbesitzt.

Page 19: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 19

Generische Klassen

template<typename T1, typename T2>

class Pair {

T1 x;

T2 y;

public:

Pair() { }

Pair(const T1 &a, const T2 &b) : x(a), y(b) { }

Pair(const Pair<T1,T2> &p) : x(p.x), y(p.y) { }

Pair<T1,T2> &operator=(const Pair<T1,T2> &p);

};

Page 20: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 20

Generische Klassen (2)

template<typename T1, typename T2>

Pair<T1,T2> &

Pair<T1,T2>::operator=(const Pair<T1,T2> &p)

{

x = p.x;

y = p.y;

return *this;

}

Variablen von diesem Typ definieren:

Pair<int,doube> p(2,1.5);

Page 21: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 21

Templates für Fortgeschrittene

• Default-Werte für Template-Parameter

• Werte (z.B. Integer) als Template-Parameter• template<int L, typename T = double>

class Vector {... };

• Spezialisierungen:– Geben für bestimmte Instanziierungen (Werte für Template-

Parameter) eine eigene Implementierung an.

– Sinnvoll, falls Standardimplementierung nicht für jedem Datentyp funktioniert, oder für bestimmte Datentypen eine effizientere Implementierung möglich ist.

Page 22: DAP2-Programmierpraktikum Einführung in C++ (Teil 1)ls11- · DAP2-Programmierpraktikum Einführung in C++ (Teil 2) Carsten Gutwenger 18. April 2008 Lehrstuhl 11 –Algorithm Engineering

Carsten Gutwenger: Einführung in C++ (Teil 2) 22

Pro und Contra Templates

Vorteile:

• Nur eine Codebasis für mehrere Implementierungen, daher leichter zu warten.

• Sehr effizienter Code, da für jeden Datentyp einzeln optimiert.

• Typsicherheit zur Kompilierzeit festellbar.

• Keine gemeinsamen Basisklassen notwendig.

Nachteile:

• Die Größe des erzeugten Codes steigt an.

• Erfordert gutes Fachwissen und Erfahrung, um Programmcode und Kompilermeldungen zu verstehen.