Nachklausur Pr31 WS'01/'02

Unterlagen und Hilfsmittel sind nicht zugelassen. Kommunikation während der Klausur ist nur mit dem Dozenten erlaubt, der Missverständnisse und Unklarheiten klären kann. Schrei­ben Sie die Lösungen auf diese Blätter, bzw. auf ein nummeriertes lee­res Blatt mit Ihrem Namen; kennzeichnen Sie die Aufgabennummer eindeutig. Geben Sie alle Blät­ter (auch die Schmier­blät­ter) ab. Für falsche oder nicht einleuchtende Lösungen be­kommen Sie grund­sätz­lich kei­ne Punk­te. Wenn aber aus Ihren Notizen oder Be­merkungen er­sicht­lich ist, dass Ihr Gedankengang richtig war, kön­nen Sie Teil­punkte bekommen. Sie ver­lie­ren jedoch diese Möglichkeit, wenn Abschreiben oder Kommu­ni­ka­ti­on wäh­rend der Klau­­sur nachgewiesen werden kann. Der Kern der Fragen (was von Ihnen erwartet wird) wurde kursiv gesetzt. Bei manchen Aufgaben steht als Orientierung der Anzahl der Programmzeilen in der Musterlösung. In den letzten 15 Minuten werden keine Fragen mehr beant­wor­tet.

Klausurtermin: 8. April 2002


Aufgabe 1: Erweitern Sie die Klasse Liste (ähnlich wie Stapel für int in der Vorlesung) um eine Methode inkr, die dafür sorgt, dass alle Zahlen in der Warteschlange inkrementiert (d.h. um 1 erhöht) werden. Die Datenstruktur der Klasse (implementiert als verkettete Liste) ist:

class Liste { protected:
   class Knoten { public: 
     Knoten(int wert, Knoten* verb) : wert(wert), verb(verb) {}
     int wert; Knoten* verb; };
   Knoten* anker;
public: ... };

Aufgabe 2: Zeichnen Sie das Einfügen in die obige Liste nach einem gegebenen Knoten:

void einfuegen(int wert, Knoten* akt) {
   akt -> verb = new Knoten(wert, akt); }

Ihre Zeichnung soll den Zustand der Liste vor und nach dem Einfügen darstellen.


Aufgabe 3: Implementieren Sie die Kopie und logische Gleichheit für die obige Klasse Liste. Zwei Liste-Objekte sind dann gleich, wenn sie dieselben int-Werte als Elemente (egal in welcher Reihenfolge) enthalten.


Aufgabe 4: Kreuzen Sie die richtigen Antworten an und geben Sie Ihre Begründung mit Stich­worten dazu. Ohne Begründung gilt Ihre Antwort als falsch.

(     )     Richtig            Die Konvertierung von Zeigern geschieht in C++ immer automatisch.
(     )     Falsch

Grund:                                                                                                                                                                                                        

(     )     Richtig            cout ist eine Stromklasse, die in der Datei iostream.h definiert wurde.
(     )     Falsch            

Grund:                                                                                                                                                                                                        

(     )     Richtig            Ein Datenabstraktionsmodul kann parameterlose Operationen enthalten,
(     )     Falsch             während ein ADT nicht.

Grund:                                                                                                                                                                                                        

(     )     Richtig            Die Implementierung einer Schablone (.cpp) muss dem Benutzer
(     )     Falsch             zur Verfügung gestellt werden.

Grund:                                                                                                                                                                                                        

(     )     Richtig            Ein new-Aufruf in einem Destruktor produziert immer eine Speicherleiche.
(     )     Falsch            

Grund:                                                                                                                                                                                                        

(     )     Richtig            Dynamisches Binden ist nur in Java möglich; in C++ wird immer statisch gebunden.
(     )     Falsch            

Grund:                                                                                                                                                                                                        

(     )     Richtig            Eine geerbte Variable kann in einem Objekt doppelt vorhanden sein.
(     )     Falsch            

Grund:                                                                                                                                                                                                        

(     )     Richtig            Die Reihungsimplementierung einer Behälterobjekts braucht weniger Speicherplatz,
(    )     Falsch             als die Listenimplementierung.

Grund:                                                                                                                                                                                                        


Aufgabe 5.: Schreiben Sie die Ziffernreihe auf, die das folgende Programm ausgibt. Schreiben Sie auch die Ziffernreihe auf, die das folgende Programm nach der Streichung der Wörter virtual ausgibt. Beschreiben Sie kurz Ihre Überlegung.

#include <iostream>
class Eins { public: virtual void m() { cout << 1 << endl; } };
class Zwei : public Eins { public: virtual void m() { cout << 2 << endl; } };
class Drei : public Eins { public: virtual void m() { cout << 3 << endl; } };
void proz1(Eins par) { par.m(); }
void proz2(Eins& par) { par.m(); }
void main() {
   Eins eins; Zwei zwei; Drei drei;
   Eins* p1 = &eins; Zwei* p2 = &zwei; Drei* p3 = &drei;
   eins.m(); zwei.m(); drei.m(); // 3 Ziffern
   p1 -> m(); p2 -> m(); p3 -> m(); // 3 Ziffern
   p1 = p2; p1 -> m();   p1 = p3; p1 -> m(); // 2 Ziffern
   eins = zwei; eins.m(); eins = drei; eins.m(); // 2 Ziffern
   proz1(zwei); proz2(drei); } // 2 Ziffern