01.03.2014 Aufrufe

Programmieren 1 - Strukturen - Klassen - Objekte

Programmieren 1 - Strukturen - Klassen - Objekte

Programmieren 1 - Strukturen - Klassen - Objekte

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

<strong>Programmieren</strong> 1 - <strong>Strukturen</strong> - <strong>Klassen</strong> - <strong>Objekte</strong><br />

‣ Funktionsabstraktion vs Datenabstraktion<br />

‣ Abstrakter Datentyp<br />

‣ <strong>Klassen</strong> – <strong>Objekte</strong><br />

‣ UML Einführung<br />

‣ Pass by value – Pass by reference<br />

‣ Prinzip des kleinsten Privilegs (const-correctness)<br />

‣ Copy-Konstruktor


Funktionsorientierte Programmierung (Veraltet)<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Fraction.h<br />

#pragma once<br />

struct Fraction {<br />

int z,n;<br />

};<br />

Fraction add(Fraction op1, Fraction op2);<br />

Fraction subtract(Fraction op1, Fraction op2);<br />

// …<br />

Domäne des Systemprogrammierers<br />

Domäne des Anwendungsprogrammierers<br />

// Anwendung: Rechnen mit Brüchen<br />

#include "Fraction.h"<br />

int main() {<br />

Fraction frac1, frac2, sum;<br />

frac1.z=1; frac1.n=2; // kein Zugriffsschutz<br />

frac2=set(frac2,3,4);<br />

sum=add(frac1,frac2);<br />

// …<br />

// Fraction.cpp<br />

#include "Fraction.h"<br />

Fraction add(Fraction op1, Fraction op2) {<br />

if(op1.n==0||op2.n==0) // PRE<br />

exit(1); // aborts program<br />

Fraction result;<br />

result.z = op1.z*op2.n+op1.n*op2.z;<br />

result.n = op1.n*op2.n;<br />

return result;<br />

}<br />

Fraction subtract(Fraction op1, Fraction op2)<br />

{ /* … */ }<br />

// …<br />

Fraction set(Fraction op,int num, int denom)<br />

if(denom==0) exit(1); // PRE<br />

op.z=num; op.n=denom;<br />

return op;<br />

}<br />

Versuch einer kontrollierten Zustandsänderung<br />

- umständlich (3 Parameter)<br />

- unverbindlich (direkter Zugriff möglich)<br />

22.04.2013 2


Funktionsorientierte Programmierung und ihre Nachteile<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Funktionsabstraktion<br />

Bruch-Anwendung aus Praktikum-Aufgabe 2 ist ein Beispiel dafür<br />

Merkmale: Programmstrukturierungsmittel sind Daten zur Zustandsspeicherung und<br />

getrennt davon die auf sie angewendeten Funktionen.<br />

Nachteile:<br />

‣Daten können ohne Initialisierung benutzt werden<br />

‣Daten können falsch initialisiert sein. Ausschließlich der Programmierer ist verantwortlich.<br />

‣Daten müssen den Funktionen übergeben werden.<br />

‣Daten und Funktionen können beliebig im Programm verteilt sein (schlecht für Fehlersuche,<br />

Wiederverwendung, Änderungen)<br />

‣Bei Änderungen in der Datenstruktur (z.B. andere Bezeichner, Datentypen oder Codierung)<br />

müssen alle Anwendungsprogramme, die diesen benutzerdefinierten Typ benutzen, geändert<br />

werden.<br />

Abhilfe: Datenabstraktion (Abstrakter Datentyp, Klasse, Datenkapselung)<br />

22.04.2013 3


Datenabstraktion<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Deshalb neues Programm-Strukturierungskonzept: Datenabstraktion<br />

‣Daten stehen im Mittelpunkt;<br />

‣Sie haben eigene Funktionen zur Verfügung, die Methoden genannt werden.<br />

‣Daten und zugehörige Funktionen werden an einer Stelle im Programm zusammen gefasst.<br />

Daraus resultiert eine bessere Pflegbarkeit, Wiederverwendbarkeit und einfachere<br />

Fehlereingrenzung.<br />

‣Nur diese Methoden haben Zugriff auf die Daten (Datenkapselung, Zugriffsschutz).<br />

‣Welche Daten (Anzahl, Typ, …) den Objektzustand beschreiben, bleibt dem Anwender<br />

verborgen (Datenabstraktion)<br />

‣Datentypen mit diesen Eigenschaften<br />

nennt man Abstrakte Datentypen (ADT)<br />

Abstrakter Datentyp =<br />

Daten + Funktionen<br />

Botschaft<br />

z<br />

n<br />

‣Anforderung:<br />

Die Programmiersprache muss<br />

diesen Datentyp unterstützen.<br />

‣C++ tut dies in Form von userdefinierten<br />

<strong>Klassen</strong>.<br />

set(zaehler,nenner)<br />

gekapselte Daten<br />

Abstrakter Datentyp<br />

22.04.2013 4


Funktionsorientiert versus Objektorientiert<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Fraction.h<br />

#pragma once<br />

struct Fraction {<br />

int z,n;<br />

};<br />

Fraction add(Fraction op1, Fraction op2);<br />

Fraction subtract(Fraction op1, Fraction op2);<br />

// …<br />

// Anwendung: Rechnen mit Brüchen<br />

#include "Fraction.h"<br />

<strong>Klassen</strong>deklaration<br />

int main() {<br />

Fraction frac1, frac2, sum;<br />

frac1.z=1; frac1.n=2; // kein Zugriffsschutz<br />

frac2=set(frac2,3,4);<br />

sum=add(frac1,frac2);<br />

// …<br />

// Fraction.h<br />

#pragma once<br />

class Fraction {<br />

int z;<br />

int n;<br />

public:<br />

Fraction add(Fraction op2);<br />

Fraction subtract(Fraction op2);<br />

// …<br />

};<br />

// Anwendung: Rechnen mit Brüchen<br />

#include "Fraction.h"<br />

int main() {<br />

Fraction frac1(1,2), frac2(3,4);<br />

Fraction sum; // Standardkonstruktoraufruf<br />

frac1.n=0;<br />

sum=frac1.add(frac2);<br />

// …<br />

Membervariable, Atrribut<br />

Alle Funktionen, die Zugriff auf<br />

Membervariable haben sollen,<br />

(Memberfunktionen) müssen in<br />

der <strong>Klassen</strong>deklaration stehen.<br />

Memberfunktion, Methode<br />

Objektdefinition mit gleichzeitiger<br />

Initialisierung durch<br />

Konstruktor<br />

Geht jetzt nicht mehr! Alle Membervariablen<br />

sind vor Fremdzugriff<br />

geschützt (Datenkapselung)<br />

Anwender muss die interne Aufrufendes Objekt (Operand 1) Memberfunktionsaufruf mittels '.'-Operator<br />

Datenstruktur der Fraction- Muss jetzt nicht mehr in der<br />

<strong>Objekte</strong> kennen! (keine Datenkapselung)<br />

Parameterliste stehen, sondern<br />

<br />

wird immer übergeben, aber nicht<br />

als Kopie sondern als Orginal<br />

22.04.2013 5


Funktionsorientiert versus Objektorientiert<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Fraction.cpp<br />

#include "Fraction.h"<br />

Fraction add(Fraction op1, Fraction op2) {<br />

if(op1.n==0||op2.n==0) // PRE<br />

exit(1); // aborts program<br />

Fraction result;<br />

result.z = op1.z*op2.n+op1.n*op2.z;<br />

result.n = op1.n*op2.n;<br />

return result;<br />

}<br />

Fraction subtract(Fraction op1, Fraction op2)<br />

{ /* … */ }<br />

// …<br />

// Fraction.cpp<br />

#include "Fraction.h"<br />

Fraction Fraction::add(Fraction op2) {<br />

if(n==0||op2.n==0) // PRE<br />

exit(1); // aborts program<br />

Fraction result;<br />

result.z = z*op2.n+n*op2.z;<br />

}<br />

result.n = n*op2.n;<br />

return result;<br />

Fraction Fraction::subtract(Fraction op2)<br />

{ /* … */ }<br />

// …<br />

Deklariert Zugehörigkeit zum<br />

Namensbereich "Fraction"<br />

Membervariable des<br />

aufrufenden Objekts<br />

Fraction set(Fraction op,int num, int denom)<br />

if(denom==0) exit(1); // PRE<br />

op.z=num; op.n=denom;<br />

return op;<br />

}<br />

void Fraction::set(int num, int denom)<br />

if(denom==0) exit(1); // PRE<br />

z=num; n=denom;<br />

return;<br />

Hier wird die Membervariable des<br />

}<br />

aufrufenden Objekts und nicht die<br />

einer Kopie desselben verändert.<br />

Rückgabe an Aufrufstelle und dort<br />

Zuweisung an Original sind deshalb<br />

nicht mehr nötig.<br />

22.04.2013 6


Funktionsorientiert versus Objektorientiert<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Fraction.cpp // Fortsetzung Fraction.cpp<br />

// Konstruktoren<br />

Hier gibt es nichts Vergleichbares!<br />

Fraction::Fraction() {<br />

z=0; n=1;<br />

Konstruktoren<br />

}<br />

Name = <strong>Klassen</strong>name<br />

Haben keinen Rückgabetyp.<br />

Fraction::Fraction( int num, int denom)<br />

if(denom==0) // PRE<br />

exit(1); // aborts program<br />

z=num; n=denom;<br />

}<br />

Membervariable des neu<br />

erzeugten Objekts<br />

Fraction::~Fraction()<br />

{<br />

Destruktor<br />

}<br />

Wird automatisch beim Verlassen des<br />

Gültigkeitsbereiches aufgerufen.<br />

Zuständig für Aufräumarbeiten.<br />

Hat hier nichts zu tun.<br />

22.04.2013 7


<strong>Objekte</strong> im Speicher<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Jedes Objekt besitzt seine eigenen<br />

Membervariablen<br />

Speicherplatz für Membervariable wird erst<br />

bei der Objektdefinition reserviert.<br />

Memberfunktionen gibt es nur einmal pro<br />

Klasse im Speicher<br />

Das aufrufende Objekt wird den Memberfunktionen<br />

stets automatisch übergeben.<br />

Über den Membervariablennamen können die<br />

Memberfunktionen direkt lesend und<br />

schreibend auf die Membervariablen des<br />

aufrufenden Objekts zugreifen.<br />

Durch ein abschließendes const in der<br />

Deklaration einer Memberfunktion kann man<br />

dieser das Schreibrecht für die Membervariablen<br />

des aufrufenden Objekts<br />

entziehen.<br />

Objekt frac1<br />

Objekt frac2<br />

z<br />

n<br />

…<br />

z<br />

n<br />

…<br />

Adresse<br />

C000<br />

C100<br />

Read-only Memberfunktion<br />

Fraction Fraction::add(Fraction op2) const {<br />

Fraction result;<br />

z = z*op2.n+n*op2.z;<br />

Geht nicht, weil Membervariablen<br />

des aufrufen-<br />

n = n*op2.n;<br />

result.z = z*op2.n+n*op2.z;<br />

den Objekts nun vor Veränderung<br />

geschützt sind.<br />

result.n = n*op2.n;<br />

return result;<br />

}<br />

OK, weil hier nicht die<br />

Membervariablen des<br />

aufrufenden Objekts<br />

geändert werden.<br />

22.04.2013 8


Unified Modelling Language (UML)<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

ermöglicht programmiersprachenunabhängige<br />

‣Spezifikation<br />

‣Visualisierung<br />

‣Konstruktion<br />

‣Dokumentation<br />

objektorientierter Softwaresysteme<br />

UML-<strong>Klassen</strong>diagramm<br />

a) niedrigster Detaillierungsgrad<br />

Fraction<br />

Klasse<br />

frac2<br />

Objekt<br />

UML kennt keine strenge visuelle Unterscheidung<br />

zwischen <strong>Objekte</strong>n und <strong>Klassen</strong>. Objektnamen sind<br />

unterstrichen, <strong>Klassen</strong>namen nicht.<br />

b) mittlerer Detaillierungsgrad<br />

Fraction<br />

-z_: int<br />

- n_: int<br />

<strong>Klassen</strong>name<br />

Attribute oder Membervariable<br />

+ Fraction()<br />

+ ~Fraction()<br />

+ add(op2:Fraction):Fraction<br />

+ cancelDown():void<br />

+ …<br />

Methoden oder Memberfktn.<br />

'+' bzw. '-' bedeutet public- bzw. private-<br />

Deklaration. Dies hat Auswirkung auf die<br />

Sichtbarkeit (kommt gleich)<br />

22.04.2013 9


Pseudocode-Notation für Algorithmen<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Pseudocode<br />

‣ soll das Wesentliche eines Algorithmus programmiersprachenunabhängig veranschaulichen<br />

‣ verdeckt viele Implementierungsdetails<br />

‣ soll intuitiv und leicht zu verstehen sein<br />

‣ besteht aus Kontroll- und Schlüsselwörtern (meist in Englisch) und natürlicher Sprache<br />

Beispiele für häufig verwendete Notationen<br />

Module<br />

program Programmname ... end Programmname<br />

klasse <strong>Klassen</strong>name { ... }<br />

Kommentare<br />

// kommentar<br />

# kommentar<br />

/* kommentar */<br />

Auswahl<br />

if ... then ... else ... end if<br />

if ... then ... fi<br />

if ... then ... else ... fi<br />

Anwendungsbeispiele<br />

Schleifen<br />

while Bedingung do ... od /* abweisend */<br />

repeat ... until Abbruchbedingung /* annehmend */<br />

for Bereichsanfang to Bereichsende step Schrittweite do … od<br />

Definition von Funktionen<br />

function Name ( Parameter ) ... end Name<br />

Zusicherungen<br />

assert …<br />

function gcd(a,b)<br />

// gibt größten gemeinsamen Teiler zurück<br />

assert a>0; assert b>0; assert a0 or b mod try>0 do<br />

try := try – 1<br />

od<br />

if Ampel rot oder gelb then<br />

stoppe<br />

else<br />

fahre weiter<br />

return try<br />

fi22.04.2013 end gcd<br />

10


Praktikumsaufgabe 2: string toString(int)<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Algorithmus in Pseudocode<br />

Rohfassung (umgangssprachlich, weniger präzise) Verfeinerung ( präziser )<br />

Algorithmus zur Umwandlung einer Ganzzahl n<br />

in eine Zeichenkette s<br />

falls n=0 gib "0" zurück<br />

bestimme und merke Vorzeichen vz<br />

erzeuge eine leere Zeichenkette s<br />

mache n positiv<br />

jetzt ist n positiv<br />

solange n > 0<br />

führe aus<br />

bestimme Einerstelle e von n<br />

erzeuge das e repräsentierende Zeichen z<br />

verkette das Zeichen z mit s<br />

streiche die Einerstelle in n<br />

verkette vz und s<br />

gib s zurück<br />

function toString(n) -> s<br />

// wandelt Zahl n in Zeichenkette s um<br />

// Eingabe: Ganzzahl n<br />

// Ausgabe: Zeichenkette s<br />

if n=0 then return "0" fi<br />

if n0 do<br />

einer := n mod 10<br />

ascii := ASCII-Code von einer<br />

Typumwandlung ascii -> z<br />

s := z + s<br />

n := n/10 /* Ganzzahldivision! */<br />

od<br />

s := vz + s<br />

return s<br />

22.04.2013 11


Praktikumsaufgabe 2: int get_int(string prompt, int min, int max)<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Algorithmus in Pseudocode<br />

function get_int(prompt,min,max) -> n<br />

// Einlesen einer Ganzzahl n im Bereich min


Hörsaalübung "Eine Motorbootfahrt mit C++"<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Zweck: Beispielanwendung "Motorboat"<br />

// Datei: MotorboatApp.cpp<br />

#include "Motorboat.h"<br />

int main(void) {<br />

Motorboat elsa; // Konstruktor<br />

elsa.howDoYouDo();<br />

elsa.castOff();<br />

elsa.howDoYouDo();<br />

elsa.faster(5);<br />

elsa.howDoYouDo();<br />

elsa.stop();<br />

elsa.howDoYouDo();<br />

elsa.dock();<br />

elsa.howDoYouDo();<br />

}<br />

// Motorboat.h: Schnittstellendeklaration.<br />

#pragma once<br />

class Motorboat {<br />

int speed_;<br />

bool isCastOff_;<br />

public:<br />

Motorboat();<br />

~Motorboat();<br />

void howDoYouDo();<br />

void castOff();<br />

void faster( int soMuch );<br />

void stop();<br />

void dock();<br />

};<br />

Motorboat<br />

- isCastOff_:bool = true<br />

- speed_:int = 0<br />

+ Motorboat()<br />

+ ~Motorboat()<br />

+ castOff():void<br />

+ howDoYouDo():void<br />

+ faster(soMuch:int):void<br />

+ dock():void<br />

22.04.2013<br />

+ stop():void<br />

13


Hörsaalübung "Eine Motorbootfahrt mit C++"<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

// Motorboot.cpp: Implementation.<br />

#include "Motorboot.h"<br />

#include <br />

#include <br />

using namespace std;<br />

Motorboat::Motorboat() {<br />

isCastOff_ = false;<br />

speed_ = 0;<br />

cout


Hörsaalübung "Eine Motorbootfahrt mit C++"<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

void Motorboat::faster(int soMuch)<br />

{<br />

if ( soMuch


Struktur und Syntax einfacher OO-Programme in C++<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

1 Systemprogrammierung, Teil 1: <strong>Klassen</strong>deklaration<br />

(Schnittstellenbeschreibung; enthält Prototypen)<br />

// Datei: NeueKlasse.h<br />

class NeueKlasse {<br />

private:<br />

attribut1;<br />

attribut2;<br />

...<br />

attributN;<br />

public:<br />

NeueKlasse();<br />

~NeueKlasse();<br />

methode1();<br />

methode2();<br />

...<br />

methodeM();<br />

};<br />

22.04.2013<br />

Privater Schnittstellenteil (default: private)<br />

Zugriffsschutz von aussen<br />

keine Speicherplatzreservierung,<br />

nur Bauplan<br />

// öffentlicher (public) Schnittstellenteil beginnt hier<br />

// Konstruktor: Kein Ergebnistyp; wird vom System auch<br />

// automatisch erzeugt.<br />

// Destruktor: Kein Ergebnistyp,<br />

// wird automatisch aufgerufen<br />

Counter<br />

- value_: int<br />

+ <br />

+ Destruktor<br />

+ set(int): void<br />

+ higher(): void<br />

+ lower(): void<br />

+ show(): void<br />

{0≤value≤10}<br />

// File: Counter.h<br />

// Class-Declaration<br />

class Counter {<br />

private:<br />

int value_;<br />

public:<br />

Counter();<br />

~Counter();<br />

void set(int);<br />

void higher();<br />

void lower();<br />

void show();<br />

};


Struktur und Syntax einfacher OO-Programme in C++<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

2 Anwendungsprogrammierung:<br />

Arbeiten mit problemangepassten Datentypen und <strong>Objekte</strong>n<br />

// Datei: main.cpp<br />

#include "NeueKlasse.h"<br />

void main(void)<br />

{<br />

NeueKlasse einObjekt;<br />

NeueKlasse einAnderesObjekt;<br />

einObjekt.methode1();<br />

einObjekt.methode2();<br />

einAnderesObjekt.methode1();<br />

}<br />

// Hier werden die Destruktoren automatisch aufgerufen<br />

// Methode1 arbeitet mit den Membervariablen von einObjekt<br />

// Methode1 arbeitet mit den Membervar von einAnderesObjekt<br />

// Std-Konstruktoraufruf; Achtung: ohne "( )"<br />

// hier wird Objekt namens "einObjekt" definiert<br />

// Memberfunktionen gibt es nur einmal<br />

// pro Klasse im Speicher<br />

// Datei: main.cpp<br />

#include "Counter.h"<br />

int main(void) {<br />

Counter myCounter;<br />

myCounter.higher();<br />

myCounter.show();<br />

myCounter.lower();<br />

myCounter.show();<br />

Counter yourCounter();<br />

yourCounter.show();<br />

int i=yourCounter.value_;<br />

return 0;<br />

}<br />

22.04.2013 //Fehler: Zugriffschutz 17


Struktur und Syntax einfacher OO-Programme in C++<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

3 Systemprogrammierung, Teil 2: <strong>Klassen</strong>definition (Implementierung der Methoden)<br />

// Datei: NewClass.cpp<br />

#include " NeueKlasse.h"<br />

NeueKlasse::NeueKlasse(){<br />

[]<br />

}<br />

NeueKlasse::~NeueKlasse() {<br />

[]<br />

Bezeichner (Name)<br />

}<br />

Namensbereich der Methode<br />

NeueKlasse::methode1(){<br />

<br />

Namensbereichauswahloperator<br />

...<br />

<br />

}<br />

...<br />

// File: Counter.cpp<br />

// Class-Implementation<br />

#include "Counter.h"<br />

#include <br />

using namespace std;<br />

Counter::Counter() { // Konstruktor<br />

value_ = 0;<br />

cout


Ein einfaches Beispiel - Datentyp Counter<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Counter<br />

- value: int<br />

+ Konstruktor<br />

+ Destruktor<br />

+ higher():void<br />

+ lower(): void<br />

+ show(): void<br />

// Datei: main,cpp<br />

#include "Counter.h"<br />

int main(void) {<br />

Counter myCounter;<br />

myCounter.higher();<br />

myCounter.show();<br />

myCounter.lower();<br />

myCounter.show();<br />

// File: Counter.h<br />

// Class-Declaration<br />

class Counter{<br />

private:<br />

int value_;<br />

public:<br />

Counter();<br />

~ Counter();<br />

void higher();<br />

void lower();<br />

void show();<br />

};<br />

// File: Counter.cpp<br />

// Class-Implementation<br />

#include "Counter.h"<br />

#include <br />

using namespace std;<br />

Counter::Counter() { // Konstruktor<br />

value_ = 0;<br />

cout


Memberfunktionen mit Parametern<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Funktionserweiterung: Zähler auf bestimmten Wert setzen<br />

// Datei: main,cpp<br />

#include "Counter.h"<br />

int main(void) {<br />

Counter myCounter;<br />

myCounter.set(10); //10 -> myCounter.value<br />

myCounter.show();<br />

}<br />

Counter yourCounter();<br />

yourCounter.set(5); //10 -> yourCounter.value<br />

yourCounter.show();<br />

return 0;<br />

// File: Counter.h<br />

// Class-Declaration<br />

class Counter<br />

{<br />

private:<br />

int value_;<br />

public:<br />

// … ommitted<br />

void set( int init );<br />

};<br />

Kopie<br />

// File: Counter.cpp<br />

// Class-Implementation<br />

// … ommitted<br />

myCounter::value_<br />

yourCounter::value_<br />

Counter::set( int init ) {<br />

//PRE: 0


Überladene Methoden/Funktionen<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

sind mehrere Methoden/Funktionen mit gleichem Namen, aber<br />

unterschiedlichem Parameterprofil (= Signatur)<br />

Parameterprofil ist bestimmt durch Anzahl, Typ und Reihenfolge der Parameter.<br />

Achtung: Der Rückgabetyp gehört nicht dazu!<br />

Beispiel<br />

//Deklaration<br />

class Counter {<br />

int value_;<br />

public:<br />

Counter();<br />

Counter(int);<br />

void higher();<br />

void higher(int);<br />

…<br />

};<br />

int<br />

higher(int);<br />

überladene Memberfunktionen<br />

ruft auf<br />

Fehler:<br />

Hat gleiche Signatur<br />

wie void higher(int)<br />

Auswahl durch Compiler;<br />

in Zusammenhang mit<br />

Typkonvertierung diejenige,<br />

die am besten passt.<br />

//Anwendung<br />

void main() {<br />

Counter c1, c2(5);<br />

c1.higher();<br />

c2.higher(5);<br />

}<br />

//Impementation<br />

void Counter::higher() { value_ = (value_


<strong>Objekte</strong> als Parameter<br />

Beispiel<br />

//Deklaration<br />

class Counter<br />

{<br />

int value_;<br />

public:<br />

// Konstruktoren<br />

void higher();<br />

void higher(int);<br />

void higher(Counter);<br />

};<br />

überladene Memberfunktionen<br />

Objekt als<br />

Parameter!<br />

//Implementation<br />

void Counter::Counter() { /* … */ }<br />

void Counter::Counter( int v ) {/* … */}<br />

void Counter::higher() {/* … */}<br />

void Counter::higher( int soViel ) {/* … */}<br />

19.04.2012<br />

//Anwendung<br />

void main() {<br />

Counter c1, c2(10);<br />

c1.higher( c2 );<br />

}<br />

ruft auf<br />

Was ist hier falsch?<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Aktion?<br />

Copy-Konstruktor<br />

wird implizit aufgerufen,<br />

um Kopie auf<br />

dem Stack zu erzeugen.<br />

void Counter::higher( Counter c ) {<br />

value_ = value_ + c.value_;<br />

}<br />

Zugriffschutz?<br />

oder besser<br />

void Counter::higher( Counter c ) {<br />

higher(c.value_); // Wiederverwendeter Code<br />

}<br />

22.04.2013 22


Vorgegebene Parameterwerte und variable Parameterzahl /113/<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Beispiel 1<br />

class Counter {<br />

int value;<br />

Counter( int init = 0 );<br />

…<br />

optionaler Parameter mit default-Wert<br />

}<br />

Konsequenz: Dieser Konstruktor<br />

• kann mit 0 oder 1 Parameter aufgerufen werden!<br />

• ersetzt Counter() und Counter(int)<br />

• ermöglicht schmalere Schnittstelle<br />

int main() {<br />

Counter c1(10);<br />

Counter c2;<br />

…<br />

}<br />

Aktueller Parameter (=10) wird benutzt<br />

Default-Wert (=0) wird benutzt<br />

//Implementation<br />

Counter::Counter( int init )<br />

{ value_ = init; }<br />

Achtung: hier (bei Implementierung) ist kein opt. Parameter erlaubt!<br />

22.04.2013 23


Überladene Methoden/Funktionen mit vorgegebenen Parametern<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Beispiel 2<br />

enum Color {red, yellow, green};<br />

class Circle {<br />

int x, y;<br />

float radius;<br />

Color c;<br />

…<br />

public:<br />

Circle();<br />

//Standard-Konstruktor<br />

Circle(int xn, int yn, float radius = 1.0f, Color f = red);<br />

Circle(int xn, int yn, Color = red, float radius = 2.0f);<br />

};<br />

// 2. Konstruktor<br />

// 3. Konstruktor<br />

//Anwendung<br />

Circle myCircle(3, 7, 2.0f, green);<br />

Circle c1(4, 26, 3.7f);<br />

Circle c2(4, 17, yellow);<br />

Circle c3;<br />

Circle c4(5);<br />

Circle c5(10,10);<br />

// 2. Konstruktor<br />

// 2. Konstruktor mit Farbe red<br />

// 3. Konstruktor mit radius= 2.0f<br />

//Standard-Konstruktor<br />

// Fehler: kein passender Konstruktor vorhanden<br />

// 2. und 3. Konstruktor würden passen.<br />

Nicht entscheidbar, deshalb Fehler!<br />

22.04.2013 24


Methoden verwenden (andere) Methoden und Attribute<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Methode ruft Methode derselben Klasse auf<br />

‣Ohne Objektname<br />

‣Mit Objektname<br />

Bezugsbereich ist dasselbe Objekt<br />

Bezugsbereich ist das andere Objekt (z.B. als<br />

Parameter übergeben; kein Zugriffschutz)<br />

Methode ruft Methode einer anderen Klasse auf<br />

‣Mit Objektname<br />

‣Ohne Objektname<br />

Bezugsbereich ist das Objekt der anderen Klasse<br />

(Zugriffschutz bei privaten Methoden und<br />

Attributen!)<br />

geht nur in bestimmten Fällen (Statische Methoden;<br />

kommt später)<br />

22.04.2013 25


dasselbe<br />

Objekt (A1)<br />

anderes Objekt derselben<br />

Klasse (ObjA)<br />

Beispiele<br />

void main(void)<br />

{<br />

KlasseA a1,a2;<br />

KlasseB b1,b2;<br />

a1.publicMethode1vonA(a2, b1)<br />

}<br />

// Datei: KlasseA.cpp<br />

void KlasseA::publicMethode1vonA<br />

( KlasseA objA, KlasseB objB )<br />

{ ...<br />

// ohne Objektname<br />

publicMethode2vonA();<br />

privateMethode2vonA();<br />

publicAttributVonA = ...;<br />

privatesAttributVonA= ...;<br />

// mit Objektname der gl. Klasse<br />

objA.publicMethode2vonA();<br />

objA.privateMethode2vonA();<br />

objA.publicMethode1vonB();<br />

objA.publicAttributVonA = ...;<br />

objA.privatesAttributVonA= ...;<br />

// Anwendung<br />

Objekt a1<br />

KlasseA<br />

Objekt a2<br />

Objekt b1<br />

KlasseB<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Objekt b2<br />

// <strong>Objekte</strong> a1 und a2 werden erzeugt<br />

// <strong>Objekte</strong> b1 und b2 werden erzeugt<br />

// publicMethode1vonA wird aufgerufen für Objekt a1 und<br />

// Parameter a2 und b1 werden übergeben.<br />

// Definition von publicMethode1vonA<br />

// verarbeitet Daten des (aufrufenden) Objekts a1<br />

// obwohl private ok, weil gleiche Klasse<br />

// Zugriff auf public-Attrib. des (aufrufenden) Obj. a1<br />

// obwohl private ok, weil gleiche Klasse<br />

// verarbeitet Daten des übergebenen objA derselben Klasse<br />

// auch ok, weil gleiche Klasse (kein Zugriffsschutz)<br />

// nicht ok, weil verschiedene <strong>Klassen</strong><br />

// ok, weil public und gleiche Klasse<br />

// auch ok, weil gleiche Klasse (kein Zugriffsschutz)<br />

// Fortsetzung auf nächster Seite<br />

22.04.2013 26


Beispiele<br />

Objekt a1<br />

KlasseA<br />

Objekt a2<br />

Objekt b1<br />

KlasseB<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Objekt b2<br />

Objekt einer anderen<br />

Klasse (objB)<br />

objB.publicMethode1vonB();<br />

objB.privateMethode1vonB();<br />

objB.publicAttributVonB = ...;<br />

objB.privateAttributVonB= ...;<br />

}<br />

// verarbeitet Daten des objB einer anderen Klasse<br />

// private! Geht nicht (Zugriff von "außen" auf geschützte<br />

// Elemente der anderen Klasse)<br />

// ok, weil public und gleiche Klasse<br />

// private! Geht nicht (Zugriff von "außen" auf geschützte<br />

// Elemente der anderen Klasse)<br />

22.04.2013 Statische Datenelemente 27


Membervariable oder lokale Variable? – Beispiel class Fraction<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

class Fraction<br />

{<br />

private:<br />

int z_,n_;<br />

Fraction result;<br />

// ...<br />

};<br />

// Falsch: nur von lokaler temporärer Bedeutung in add(Fraction b)<br />

Fraction Fraction::multiply(Fraction b)<br />

{<br />

Fraction result;<br />

result.z_ = … ;<br />

result.n_ = … ;<br />

return result;<br />

}<br />

Merke: Membervariable sollen nicht nur von lokaler und/oder temporärer<br />

Bedeutung sein<br />

Dies ist eine Ausprägung des Problemlösungsprinzips<br />

KISS (Keep It Small and Simple)<br />

22.04.2013 28


Konzept der friend-Funktionen<br />

FB Informatik<br />

Prof. Dr. R.Nitsch<br />

Die globale Funktion Fraction get_Fraction(string prompt) ist eng mit der<br />

Klasse Fraction verbunden, gehört aber nicht zu ihrem Namensbereich. Deshalb<br />

schützt die Klasse auch ihre privaten Attribute vor dem Zugriff dieser Funktion.<br />

Eine erfolgreiche Beziehung zwischen einem Subunternehmer und seinem<br />

Generalunternehmer ist auf enge, direkte Zusammenarbeit angewiesen. So wird i.A.<br />

der Subunternehmer direkten Zugriff auf bestimmte Informationen des<br />

Gerneralunternehmers haben.<br />

Das gleiche Erfolgsrezept wird im Bereich der <strong>Klassen</strong> mit dem friend-Konzept<br />

verwirklicht.<br />

Durch eine friend-Deklaration kann der Zugriffschutz selektiv für bestimmte<br />

Funktionen (oder <strong>Klassen</strong>) aufgehoben und der direkte Zugriff auf alle Attribute<br />

gewährt werden.<br />

Beispiel:<br />

class Fraction {<br />

private:<br />

int z_, n_;<br />

public:<br />

friend Fraction get_Fraction(string prompt);<br />

friend class TestFraction;<br />

Fraction get_Fraction(string prompt){<br />

Fraction frac;<br />

cout frac.z_>>frac.n_;<br />

// …<br />

}<br />

Zugriff von "aussen"<br />

möglich durch friend-Eigenschaft!<br />

gewährt der bezeichneten Funktion direkten<br />

Zugriff auf alle privaten Attribute (hier: z_, n_).<br />

…<br />

};<br />

gewährt der Klasse TestFraction, d.h.allen Memberfunktionen dieser<br />

Klasse direkten Zugriff auf alle privaten Attribute (hier: z_, n_).<br />

22.04.2013 <strong>Klassen</strong>-Schnittstelle 29

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!