summaryrefslogtreecommitdiffstats
path: root/Bachelor/Prog2/Z-Uebung/Z-Uebung.htm
blob: 0790d88d7ff4519b975b7bd0b4852582ee00ec5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <meta name="Author" content="Hans-Peter Weber">
   <meta name="GENERATOR" content="Microsoft FrontPage 5.0">
   <title>Klausur SS 04</title>
</head>
<body>
&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td WIDTH="25%" BGCOLOR="#EFEFDE">FH Darmstadt&nbsp;
<br>FB Informatik
<p>Prof.Dr.H.P.Weber</td>

<td>
<p align="center">
<center><font size=+3>Programmieren II</font></center>
<br> 
<center><font size="+3">�bung</font></center>
</td>

<td WIDTH="25%" BGCOLOR="#EFEFDE">
<center>
<p><font size="6">&nbsp;&nbsp;&nbsp; </font><font size="5">Juni 2005</font></p>
</center>
</td>
</tr>
</table>

<br>

<table>
<tr VALIGN=TOP>
<td>Es soll die folgende Klassenhierarchie f�r zweidimensionale Figuren 
implementiert werden:<br>
  Abstrakte Basisklasse <b><tt>Shape</tt></b>, davon direkt abgeleitet die
  Klassen <b><tt>
Polyline</tt></b>  und <b><tt>Ellipse</tt></b>. Von <b><tt>
Polyline</tt></b>  direkt abgeleitet die Klassen <b><tt>L</tt></b><b><tt>ine</tt></b> 
  und <b><tt>Polygon</tt></b> und zus�tzlich von <b><tt>Polygon</tt></b>
  abgeleitet die Klasse <b><tt>Rectangle</tt></b>. Au�erdem von <b><tt>Ellipse</tt></b>
  abgeleitet die Klasse <b><tt>Circle</tt></b>.</td>
</tr>
</table>

<br>

<table WIDTH="100%" BGCOLOR="#EFEFDE" >
<tr>
<td>Teil 1:</td>
</tr>
</table>

<p>Zun�chst werden nur die grundlegenden Klassen <b> <tt>Shape</tt></b> und <b> <tt>
Polyline</tt></b> entwickelt und getestet. Da die Klassen der <b> <tt>Shape</tt></b>-Hierarchie 
mit Punkten arbeiten, wird zur Darstellung eines Punktes auch eine Klasse <b> <tt>
Point</tt></b> definiert:</p>
<ul>
<li>
Die Klasse <b> <tt>Point</tt></b> besitzt die <b> <tt>public</tt></b>-Elemente <tt> <b> 
x</b></tt> und <b> <tt>y</tt></b> vom Typ <b><tt>double</tt></b> und einen 
entsprechenden Konstruktor mit zwei Parametern, die beide den Default-Wert <tt>
<b> 0.0</b></tt> haben.<br>
Die Methode <b> <tt>distance</tt></b> liefert den Abstand zu einem zweiten 
Punkt, der als Argument �bergeben wird. Der Abstand von zwei Punkten (x1, y1) 
und (x2, y2) ist die Wurzel aus (x2 - x1)<sup>2</sup> + (y2 - y1)<sup>2</sup> .
<br>
Die Methode <b> <tt>toString</tt></b> liefert den Punkt als String in der Form <b> <tt>
(x, y)</tt></b>.<br>
Der Operator <b> <tt>*=</tt></b> multipliziert den Punkt mit einer 
Gleitpunktzahl.<br>
Au�erdem werden die folgenden globalen Operationen bereitgestellt:<br>
<b> <tt>+</tt></b> und <b> <tt>-</tt></b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Liefert die Summe bzw. Differenz zweier Punkte.<br>
<b> <tt>==</tt></b> und <b> <tt>!=</tt></b>&nbsp;&nbsp;&nbsp; Vergleicht zwei 
Punkte.<br>
<b> <tt>&lt;&lt;</tt></b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Gibt einen Punkt auf einen Stream aus.</li>
<li>
Die <b> <tt>Shape</tt></b>-Klasse enth�lt ein Attribut <b> <tt>anchor</tt></b> (Anker, 
Bezugspunkt), das die Lage der Figur festlegt. Durch Verschiebung des Ankers 
wird also die gesamte Figur verschoben. Der Anker wird in der <b> <tt>Shape</tt></b>-Klasse 
als <b> <tt>protected</tt></b>-Element gespeichert. Der Konstruktor
initialisiert den Anker mit dem als Argument �bergebenen Punkt oder mit dem
Default-Wert <b><tt>Point(0,0)</tt></b>. Zugriffsmethoden erlauben das Lesen und
Setzen des Ankers. Die Verschiebung erfolgt mit der Methode <b><tt>move</tt></b>,
die zwei Parameter f�r die Verschiebung in x- und y-Richtung besitzt.</li>

<li>
Die Klasse <b><tt>Shape</tt></b> ist eine abstrakte Klasse. Neben dem virtuellen
Destruktor stellt sie das folgende polymorphe Interface bereit: Die Methode <tt><b>toString</b></tt>
liefert die Daten einer Figur als String. F�r die Klasse <b><tt>Shape</tt></b>
sind das die Koordinaten des Ankers. Au�erdem enth�lt <b><tt>Shape</tt></b>
die rein virtuellen Methoden <b><tt>scale</tt></b> und <b><tt>draw</tt></b>. <b><tt>scale</tt></b>
verkleinert oder vergr��ert die Figur um einen Faktor, der als Argumnet
�bergeben wird. Die Methode <b><tt>draw</tt></b> wird zum Zeichnen einer Figur 
bereitgestellt, aber nicht genutzt (d.h. leer implementiert).</li>

<li>
Die Klasse <b> <tt>Polyline</tt></b> stellt einen Linienzug dar. Beispielsweise
besteht folgender Linienzug : Anker - E1 - E2 - E3 - E4 aus vier Linien mit den Endpunkten E1 bis E4. Die Endpunkte werden relativ zum
Anker in einem dynamisch erzeugten Array gespeichert. Entsprechend besitzt die
Klasse <b><tt>Polyline</tt></b> zwei Datenelemente: Ein dynamisches Element,
n�mlich einen Zeiger auf das Array mit <b> <tt>Point</tt></b>-Elementen, und
eine Variable f�r die Anzahl der Linien. Definieren Sie verschiedene
Konstruktoren: Einen Default-Konstruktor, einen Konstruktor mit einem <b> <tt>Point</tt></b>-Parameter
zur Festlegung des Ankers, einen Konstruktor mit zwei <b> <tt>Point</tt></b>-Parametern
f�r eine Linie und einen Konstruktor, dem ein Array mit den Punkten eines 
Linienzuges und die Anzahl der Punkte �bergeben werden. Jeder Konstruktor setzt
den Zeiger und die Anzahl der Linien auf <b><tt>0</tt></b>, wenn das Objekt noch
keine Linie enth�lt. Andernfalls erzeugt der Konstruktor dynamisch das Array f�r 
die Endpunkte gem�� der aktuellen Anzahl Linien. F�r jeden Endpunkt wird
die Differenz zum Anker gespeichert. Das dynamische Array wird vom Destruktor
wieder freigegeben. Da die Klasse <b><tt>Polyline</tt></b> ein dynamisches
Element besitzt m�ssen auch Kopierkonstruktor und Zuweisungsoperator definiert
werden.</li>

<li>
Redefinieren Sie f�r die Klasse <b><tt>Polyline</tt></b> alle rein virtuellen 
Methoden der Klasse <b><tt>Shape</tt></b> und die Methode <tt><b>toString</b></tt>, die 
die Koordinaten der Eckpunkte als String liefert.
Stellen Sie ferner eine Methode bereit, die die Anzahl Linien im Polygon
zur�ckgibt, und eine Methode, die die Gesamtl�nge liefert.</li>

<li>

�berladen Sie schlie�lich zweimal den <b><tt>operator+=</tt></b>: Ist das
Argument ein Punkt, soll eine weitere Linie zu diesem Punkt angeh�ngt werden.
Ist das Argument ein <b><tt>Polyline</tt></b>-Objekt, soll dessen gesamter
Linienzug an den letzten Punkt angeh�ngt werden.
<ul>
<li>
Wenn eine Linie angeh�ngt wird, muss das Array mit den Endpunkten vergr��ert
werden.
</li>
<li>
Zu den relativen Koordinaten des anzuh�ngenden Linienzugs m�ssen die relativen
Koordinaten des letzten Punktes addiert werde.
</li>
</ul>
Testen Sie die Klasse <b><tt>Polyline</tt></b>, indem Sie mit jedem zur
Verf�gung stehenden Konstruktor ein Objekt erzeugen und sich anzeigen lassen.
Rufen Sie dann jede Methode der Klasse mindestens einmal auf.</li>

</ul>

<table WIDTH="100%" BGCOLOR="#EFEFDE" >
<tr>
<td>Teil 2:</td>
</tr>
</table>

<p>Erg�nzen Sie die <b> <tt>Shape</tt></b>-Klassenhierarchie um die noch
fehlenden Klassen <b><tt>Line</tt></b>, <b><tt>Polygon</tt></b>, <b><tt>Rectangle</tt></b>,
<b><tt>Ellipse</tt></b> und <b><tt>Circle</tt></b>:</p>
<ul>
<li>
Die Klasse <b><tt>Line</tt></b> besitzt mindestens zwei Konstruktoren: Die
Endpunkte einer Linie sollen als zwei <b><tt>Point</tt></b>-Objekte oder direkt
in x-, y-Koordinaten angegeben werden k�nnen. Die Redefinition von geerbten
Methoden ist nicht notwendig. Allerdings soll es nicht m�glich sein, an eine
Linie einen weiteren Punkt oder einen Linienzug anzuh�ngen!</li>
<li>
Ein <b><tt>Polygon</tt></b> wird als geschlossener Linienzug betrachtet: Die Linie vom letzten
Punkt zum ersten Punkt (=Anker) geh�rt logisch zur Figur. Entsprechend m�ssen
die Methoden redefiniert werden, die die Anzahl Linien bzw. die Gesamtl�nge
zur�ckgeben. Stellen Sie zus�tzlich Methoden bereit, die die Anzahl Ecken (=
Anzahl Linien) und den Umfang (=Gesamtl�nge) liefern:</li>
<li>
Die Klasse <b><tt>Rectangle</tt></b> beschreibt Vierecke mit der linken unteren
Ecke als Anker, deren Seiten parallel zu den x- und y-Koordinaten verlaufen.
Definieren Sie zuerst einen Konstruktor, dem der Anker sowie die Breite und
H�he des Rechtecks �bergeben wird. Ein zweiter Konstruktor erzeugt ein
Rechteck aus zwei Punkten, n�mlich der linken unteren Ecke und der rechten
oberen Ecke. Stellen Sie Methoden bereit, die die H�he und Breite des Rechtecks
liefern. Auch f�r Rechtecke soll es nicht m�glich sein, einen weiteren Punkt
oder einen Linienzug anzuh�ngen.</li>

<li>
Definieren Sie schlie�lich die Klassen <b><tt>Ellipse</tt></b> und <b><tt>Circle</tt></b>.
Eine Ellipse wird durch den Mittelpunkt und die beiden Halbachsen a und b
beschrieben. Der Mittelpunkt ist der Anker der Figur. Neben einem Konstruktor
und den Zugriffsmethoden f�r die Halbachsen soll auch eine Methode definiert
werden, die den Umfang der Ellipse liefert (Verwenden Sie zur Berechnung des
Umfangs einer Ellipse die N�herungsformel U = PI * ( 3/2*(a+b) - sqrt(a*b) )
wobei PI = 3.14159). Au�erdem m�ssen die geerbten Methoden <b><tt>scale</tt></b> 
und <b><tt>toString</tt></b> redefiniert werden.</li>

<li>
Ein Kreis ist eine Ellipse, deren Halbachsen gleich lang sind und den Radius des
Kreises bilden. Au�er einem Konstruktor soll die Klasse <b><tt>Circle</tt></b>
zus�tzlich die Methoden <b><tt>getRadius</tt></b> und <b><tt>setRadius</tt></b>
bereitstellen. Auch ist die Methode <b><tt>toString</tt></b> zu redefinieren.</li>

<li>

Erweitern Sie das Anwendungsprogramm aus Teil 1 so, dass auch die neuen Klassen
getestet werden.
</li>

</ul>


<table WIDTH="100%" BGCOLOR="#EFEFDE" >
<tr>
<td>Teil 3:</td>
</tr>
</table>

<p>Die Figuren eines 'Bildes' bestehend aus Objekten der <b> <tt>Shape</tt></b>-Hierarchie
werden in einer verketteten Liste verwaltet und in der Reihenfolge 'gezeichnet',
wie sie in der Liste vorkommen. Dazu soll <b><tt>std::list</tt></b> aus der STL
verwendet werden:</p>

<ul>
<li>
Zur Realisierung einer inhomogenen Liste werden nicht die Objekte selbst sondern
<tt><b>Shape</b></tt>-Zeiger in der&nbsp;Liste gespeichert. Dem Listentyp soll
daher der Name <b><tt>ShapePtrList</tt></b> mittels <b><tt>typedef</tt></b>
zugewiesen werden. Danach k�nnen Objekte dieses Typs angelegt und die in <b><tt>std::list</tt></b>
vorhandenen Methoden aufgerufen werden, z.B. wird mit <b><tt>push_back</tt></b>
ein <tt><b>Shape*</b></tt> auf ein zuvor erzeugtes Objekt der <tt><b>Shape</b></tt>-Hierarchie
an die Liste angeh�ngt.</li>
<li>
Schreiben Sie ein Anwendungsprogramm, das Zeiger auf verschiedene Objekte der <tt><b>Shape</b></tt>-Hierarchie
in eine Liste vom Typ <b><tt>ShapePtrList</tt></b>  einf�gt. Die Objekte sollen
mit <tt><b>new</b></tt> dynamisch erzeugt werden. Geben Sie die <tt><b>Shape</b></tt>-Objekte
der Liste aus. L�schen Sie dann einige Elemente und zeigen Sie die Liste erneut
an. Schreiben Sie zur Ausgabe der <tt><b>Shape</b></tt>-Objekte eine globale
Funktion <b><tt>printShapeList</tt></b>, die als Argument eine Referenz auf die
Liste erh�lt und mithilfe der Methoden <b><tt>t</tt></b><b><tt>oString</tt></b>
die <tt><b>Shape</b></tt>-Objekte der Liste anzeigt. Geben Sie zus�tzlich mit
dem Operator <b><tt>type</tt></b><b><tt>id</tt></b> auch den Typ der Objekte
aus.</li>
</ul>

<table WIDTH="100%" BGCOLOR="#EFEFDE" >
<tr>
<td>Teil 4:</td>
</tr>
</table>

<p>Die Klasse <b><tt>ShapePtrList</tt></b>  wird noch in zwei Schritten
verbessert:</p>

<ul>
<li>
Bisher speichert jedes Listenelement einen einfachen <tt><b>Shape</b></tt>-Zeiger.
Deshalb wird beim L�schen eines Listenelements nur der Zeiger nicht aber das <tt><b>Shape</b></tt>-Objekt
selbst gel�scht, was zu Speicherlecks f�hrt. Ebenso werden beim Kopieren und
Zuweisen ganzer Listen nur die Zeiger kopiert ('flache Kopie'), was gravierende
Laufzeitfehler verursachen kann. Daher sollen die Zeiger durch 'intelligente
Zeiger (smart pointer)' ersetzt werden, die z.B. das adressierte Objekt
zerst�ren, wenn sie selbst zerst�rt werden. Gehen Sie dazu wie folgt vor:</li>
<ul>
<li>
Erg�nzen Sie zuerst die <tt><b>Shape</b></tt>-Klasse durch eine rein virtuelle
Methode <tt><b>clone</b></tt>. Diese Methode muss in jeder abgeleiteten Klasse 
redefiniert werden, indem sie eine dynamisch erzeugte Kopie des aktuellen 
Objekts zur�ckgibt.</li>
<li>
Definieren Sie dann die Klasse <b><tt>ShapePtr</tt></b>  zur Darstellung eines
intelligenten Zeigers auf <tt><b>Shape</b></tt>-Objekte. Als Attribut besitzt
die Klasse einen <tt><b>Shape</b></tt>-Zeiger, der vom Konstruktor mit dem
Parameter vom Typ <tt><b>Shape*</b></tt> bzw. dem Default-Wert 0 initialisiert
wird. Au�erdem muss ein eigener Kopierkonstruktor definiert werden. Dieser
erzeugt zun�chst mithilfe der Methode <tt><b>clone</b></tt> eine Kopie des <tt><b>Shape</b></tt>-Objekts
und l��t den <tt><b>Shape</b></tt>-Zeiger auf diese Kopie zeigen. Der
Destruktor zerst�rt das <tt><b>Shape</b></tt>-Objekt, auf das der Zeiger
verweist. Der Zuweisungsoperator wird zweifach �berladen, so dass sowohl ein
anderes <tt><b>ShapePtr</b></tt>-Objekt als auch ein einfacher <tt><b>Shape</b></tt>-Zeiger
zugewiesen werden kann. In beiden F�llen wird das aktuelle <tt><b>Shape</b></tt>-Objekt
zerst�rt und der Zeiger auf eine Kopie des <tt><b>Shape</b></tt>-Objekts
gesetzt, auf das der �bergebene Zeiger verweist. Die Operatoren <tt><b>*</b></tt>
und <tt><b>-&gt;</b></tt> sind so zu �berladen, dass ein <tt><b>ShapePtr</b></tt>-Objekt
wie ein gew�hnlicher Zeiger verwendet werden kann. Der
Dereferenzierungsoperator liefert eine Referenz auf das adressierte <tt><b>Shape</b></tt>-Objekt
und der Pfeiloperator liefert den <tt><b>Shape</b></tt>-Zeiger selbst.
Schlie�lich soll auch eine Konvertierung eines <tt><b>ShapePtr</b></tt>-Objekts
in einen <tt><b>Shape</b></tt>-Zeiger m�glich sein. F�gen Sie deshalb noch die
entsprechende Konvertierungsfunktion hinzu.</li>
</ul>
Die Definition der Liste mit Zeiger auf <tt><b>Shape</b></tt>-Objekte lautet nun
wie folgt:<br>
<tt><b>typedef List&lt; ShapePtr &gt; ShapePtrList;<br>
</b></tt>Stellen Sie die Definitionen der Klassen <tt><b>ShapePtr</b></tt> und <tt><b>ShapePtrList</b></tt>
in eine neue Header-Datei <tt><b>ShapeList.h</b></tt>. Verwenden Sie zum Testen
die Funktionen <tt><b>main</b></tt> und <tt><b>printShapeList</b></tt> aus Teil
3. Diese sollten unver�ndert mit der neuen Definition der Liste lauff�hig
sein.
<li>
Um die Klasse <tt><b>ShapePtrList</b></tt> mit eigenen Methoden erweitern zu
k�nnen, wird jetzt die Klasse <tt><b>ShapePtrList</b></tt> von der
Standardklasse <tt><b>std::list</b></tt> abgeleitet:<br>
<tt><b>class ShapePtrList : public list&lt; ShapePtr &gt;<br>
</b></tt>Erg�nzen Sie die Klasse <tt><b>ShapePtrList</b></tt> durch die
Methoden <tt><b>scale</b></tt> und <tt><b>toString</b></tt>. Die Methode <tt><b>scale</b></tt>
verkleinert oder vergr��ert jede Figur der Liste um einen Faktor, der als
Argument �bergeben wird. Die Methode <tt><b>toString</b></tt> liefert einen
String mit dem Inhalt der Liste: F�r jede Figur der Liste wird in einer neuen
Zeile zuerst der Typname der Figur in den String geschrieben und dann das
Ergebnis der Aufrufes der <tt><b>toString</b></tt>-Methode f�r die jeweilige
Figur.
</li>
</ul>
Testen Sie die verbesserte Klasse
<tt><b> ShapePtrList</b></tt>. �ndern Sie die&nbsp; <tt><b>main</b></tt>-Funktion
aus Teil 3 wie folgt: Entfernen Sie die globale Funktion <tt><b>printShapeList</b></tt> 
und verwenden Sie zur Ausgabe der Liste die Methode <tt><b>toString</b></tt>.
Erzeugen Sie eine Kopie der Liste und modifizieren Sie die Figuren der neuen
Liste durch einen Aufruf der Methode <tt><b>scale</b></tt>. Nur die Figuren der
neuen Liste d�rfen sich dadurch ver�ndern. Testen Sie auch die Zuweisung
ganzer Listen. Den Aufruf der Destruktoren k�nnen Sie sichtbar&nbsp; machen,
indem Sie im virtuellen Destruktor der Klasse <tt><b>Shape</b></tt>  eine
Meldung ausgeben.
<br>

<table>
<tr>
<td COLSPAN = 2>
<hr width="100%">
<font size=-1>Quelle: Prinz / Kirch-Prinz: C++ Das �bungsbuch</font>
<br>
</td>
</tr>
</table>

</body>