Zurück

Objektorientierte Programmierung

Übungen

Übung 2-1

Dies und das

Zu Beginn ein paar kurze Verständnisfragen.

  1. Wozu dienen die Schutzbereiche private und public im Rahmen der objektorientierten Programmierung?
  2. Was ist der Unterschied zwischen einer Klasse und einem Objekt?
  3. Wozu dient ein Konstruktor?
  4. Wieviele Konstruktoraufrufe durchläuft ein Objekt im Laufe seiner Lebensdauer?
  5. Welche Konstruktoren besitzt jede C++-Klasse? Wie sieht dies in Java aus?
  6. Weshalb deklariert man in C++ bei einer get-Methode, die etwas vom Typ char * zurückliefert, üblicherweise den Rückgabetyp als const char *? Wieso ist eine ähnliche Kennzeichnung bei der entsprechenden Java-Methode, die etwas vom Typ String zurückliefert, nicht erforderlich?
  7. Was besagt das nachgestellte const bei einer C++-Methode (innerhalb einer Klasse)?
  8. Weshalb ist main() in Java eine static-Methode?

Übung 2-2

Elementare Klassenbildung

Modellieren und implementieren Sie bitte die (eventuell in der Vorlesung bereits als PräsenzÜbung begonnene) Klasse PhoneNumber - jeweils in C++ und in Java.

  1. Ein konkretes Objekt dieser Klasse PhoneNumber steht für genau eine Festnetz- oder Mobilnummer.
  2. Es gibt Methoden, mit denen die Länder- und die Netzvorwahl abgerufen werden können (get-Methoden).
  3. Die Ausgabe-Methode ausgabe() dieser Klasse ist parametrisierbar und kann damit wahlweise die Ausgabe in der kurzen Form "0171 2468013" oder einer der internationalen Schreibweisen durchführen.
    Dies bedeutet beispielsweise, dass bei ausgabe(0) die o.g. Kurzschreibweise ausgegeben wird, bei ausgabe(1) eine der internationalen Notationen.
  4. Zwei Objekte dieser Klasse können mit einer Methode equals() auf inhaltliche Gleichheit geprüft werden.
  5. Zu dieser Klasse werden "sinnvolle" Konstruktoren bereitgestellt. (Was "sinnvoll" ist, dürfen Sie natürlich entscheiden; mindestens gefordert ist jedoch der u.g. Default-Konstruktor.)
// Code-Beispiel in C++
class PhoneNumber 
{
   private:
      ...                  // Attributfestlegungen

   public:
      PhoneNumber();       // Default-Konstruktor
      // ... ggf. weitere Konstruktoren 
      const char * getLaendervorwahl() const;
      const char * getNetzvorwahl() const;

      void ausgabe(int) const;      // Ausgabemethode - parametrisiert fuer die verschiedenen Darstellungsformen

      // Hier kommt mindestens noch die o.e. Methode equals() hinzu. 

}; // end class PhoneNumber



Übung 2-3

Die Klassen Anschrift und Student

Nachstehend finden Sie Deklarationen für die Klassen Anschrift und Student. Vervollständigen Sie hier bitte die u.a. Implementierungen in C++ sowie in Java, so dass Sie zu einem kleinen lauffähigen Programm gelangen. Dabei dürfen Sie selbstverständlich beide Klassen gerne auch noch um weitere Methoden (und/oder Konstruktoren) erweitern.

class Anschrift
{
   private:
      char strasse[120];
      char hausnr[20];
      char plz[10];
      char ort[120];
      char telnr[30];

   public:
      Anschrift();
      Anschrift(char*,char*,
                char* = "51465",char* = "Bergisch Gladbach");
                
      const char * getStrasse() const;
      const char * getHausnr() const;
      const char * getPlz() const;
      const char * getOrt() const;
      const char * getTelnr() const;
      
      // ... weitere Methoden ...             

};


// ==========================================================================================

class Student  
{
   private:
      char matnr[8];       // 7-stellige Matrikelnummer 
      char nachname[80];   // Nachname des Studierenden
      char vorname[80];    // Vorname des Studierenden
      Anschrift semesterAdresse; // Anschrift des Studierenden waehrend der Hochschulphase
      Anschrift privatAdresse;   // Private Anschrift des Studierenden 
 
   public:
      Student(const char *, const char *, const char *, Anschrift, Anschrift);   

      // ... weitere Methoden ...             

};

public class Anschrift                
{
   private String strasse;
   private String hausnr;
   private String plz;
   private String ort;
   private String telnr;

   public Anschrift() { ... } // Die drei Punkte bedeuten etwas Arbeit fuer Sie... 
   public Anschrift(String strasse, String hausnr, String plz, String ort, String telnr) { ... } 
   public String getStrasse() { ... } 
   public String getHausnr() { ... } 
   public String getPlz() { ... } 
   public String getOrt() { ... } 
   public String getTelnr() { ... } 
      
   // ... weitere Methoden ...             

}


// ==========================================================================================
// Zur Erinnerung: in Java ist jede public-Klasse in einer 
// eigenen .java-Datei abzulegen. 
public class Student  
{
   private String matnr; // 7-stellige Matrikelnummer 
   private String nachname;
   private String vorname;
   private Anschrift semesterAdresse;
   private Anschrift privatAdresse;
 
   public Student(String matnr, String nachname, String vorname,
                  Anschrift semesterAdresse, Anschrift privatAdresse) { ... }
   // ... weitere Methoden ...             

};

Übung 2-4

Die Klasse Bruch in C++

Nachstehend finden Sie die Datei brueche.cpp, in der eine einfache (rudimentäre) Klasse Bruch definiert wird. Auf dieser Version wollen wir im Folgenden aufsetzen. Hier noch einmal die Vereinbarung dieser Klasse.

class Bruch
{
   private:
      int z, n;            // Zaehler und Nenner

   public:
      Bruch();             // Default-Konstruktor
      Bruch(int,int);      // Konstruktor
      Bruch addiere(Bruch);
      void Ausgabe();
}; // end class Bruch
  1. Nehmen Sie bitte eine Methode eingabe() in die Klasse Bruch auf, die für die (korrekte) Eingabe eines gültigen Bruches sorgt. Das heißt: Zähler und Nenner können beliebige int-Werte sein, der Nenner darf jedoch nicht 0 sein! Sollte ein Anwender für den Nenner 0 eingeben, so ist die Eingabe des Nenners zu wiederholen.
  2. In der Datei kuerzen.cpp [hierfür öffnet sich ein neues Browser-Fenster oder - je nach Konfiguration - ein Editor] stehen die beiden Hilfsfunktionen kuerzen() und GGT() [vgl. auch die Kommentare in der Datei].
    Nehmen Sie diese beiden Funktionen bitte mit auf in die Klasse Bruch und sorgen Sie dafür, dass von nun an alle Brüche, mit denen Sie arbeiten, stets gekürzt sind! - In welchen Methoden müssen Sie dies berücksichtigen?
  3. Erweitern Sie die Klasse Bruch bitte um die naheliegenden Methoden subtrahiere(), multipliziere(), dividiere().
    [Sie dürfen diese Methoden auch umbenennen... Ausblick: später ersetzen wir sie sowieso durch die in C++ naheliegendere Operatorschreibweise!]
  4. Ergänzen Sie zu Testzwecken die Klasse Bruch bitte so, dass in jedem Konstruktor eine kurze Bildschirmausgabe erscheint ("Hier meldet sich der Konstruktor...").
  5. Ergänzen Sie schließlich die Klasse um einen Destruktor, der als einzige Aktion ebenfalls eine kleine Meldung ("Hier meldet sich der Destruktor...") ausgibt.

// ------------------------------------------------------------------------
// Dateiname:   brueche.cpp
// Aufgabe:     Elementare Arbeit mit Bruchen zur Erlaeuterung des
//              Klassenbegriffs.
// ------------------------------------------------------------------------

#include <iostream>
#include <cstdlib>
using namespace std;

class Bruch
{
   private:
      int z, n;            // Zaehler und Nenner

   public:
      Bruch();             // Default-Konstruktor
      Bruch(int,int);      // Konstruktor
      Bruch addiere(Bruch);
      void ausgabe();
};

// Implementation der Klassen-Methoden (Mitgliedsfunktionen)
// ---------------------------------------------------------

Bruch::Bruch()             // Default-Konstruktor
{
   z=0;
   n=1;
} // end Bruch::Bruch()

Bruch::Bruch(int zaehler, int nenner) // weiterer Konstruktor
{
   // Minimale Notfallbehandlung bei nenner==0 ! 
   if (nenner!=0)
   {
      z=zaehler;    // ausfuehrlich:  this->z=zaehler;
      n=nenner;     // this ist ein Zeiger auf das aktuelle Objekt
   }
   else
   {
      z=0;
      n=1;
   }
} // end Bruch::Bruch(int,int)

Bruch Bruch::addiere(Bruch q1)
{
   Bruch q;
   q.z = z*q1.n + q1.z*n;
   q.n = n * q1.n;
   return(q);
} // end Bruch::addiere 

void Bruch::ausgabe()
{
   cout << z << "/" << n;
} // end Bruch::ausgabe

// ---------------------------------------------------------

int main() // synonym fuer int main(void) 
{
   Bruch q1(1,1), q2(1,2), q3;    // q3 ist defaultmaessig 0/1

   // Die Anweisung q1.z=1; ist nun illegal, da z ein privates
   // Datenelement des Objektes q1 ist!

   // Addieren von q1 und q2 in die Variable q3     
   q3=q1.addiere(q2);

   // Ausgabe der Summe 
   q1.ausgabe();
   cout << " + ";
   q2.ausgabe();
   cout << " = ";
   q3.ausgabe();
   cout << endl;

   return EXIT_SUCCESS;

} // end main 

// end of file brueche.cpp 

Übung 2-5

Die Klasse Bruch in Java

Übertragen Sie die C++-Implementierung der Klasse Bruch bitte nach Java. Hier sollen die gleichen Funktionalitäten bereitstehen wie in der obigen C++-Realisierung. (Lediglich der in C++ bereitgestellte Destruktor entfällt in der Java-Version.)

// Code-Auszug in Java 
public class Bruch
{
   // ...

   public static void main(String[] args)
   {
      Bruch b1 = new Bruch(1,1);
      Bruch b2 = new Bruch(1,2);

      System.out.print("b1: ");
      b1.ausgabe();
      System.out.print("b2: ");
      b2.ausgabe();

      System.out.println("Addition ergibt: " + b1.addiere(b2));
      System.out.println("Subtraktion ergibt: " + b1.subtrahiere(b2));
      // ...
   }

}

Übung 2-6

Schach

Schachfiguren; Quelle wikimedia.org Sie kennen das Schachspiel? Dieses strategische Brettspiel operiert auf einem 8 x 8 - Spielbrett, bei dem die nebeneinanderliegenden Felder abwechselnd weiß und schwarz (respektive hell und dunkel) gefärbt sind.

Zwei Spieler, deren Figuren ebenfalls weiß bzw. schwarz gekennzeichnet sind, spielen gegeneinander nach bestimmten Regeln, die an dieser Stelle indes nichts zur Sache tun. Jeder Spieler besitzt (zu Spielbeginn jedenfalls) die folgenden Figuren: acht Bauern und je zwei Türme, Springer und Läufer sowie je eine Dame und einen König.

Modellieren Sie bitte eine Klasse ZSchach, die eine konkrete Spielsituation eines Schachspiels darstellt. Das bedeutet, dass auf den 64 Spielfeldern jeweils maximal eine konkrete Figur stehen oder das Feld natürlich auch leer sein kann. Außerdem ist zu verwalten, welcher Spieler als nächstes am Zug ist.

Der Name ZSchach soll abgekürzt "(einzelner) Zustand eines Schachspiels" bedeuten.
Wer sich über das Spiel umfassender informieren möchte, dem sei u.a. zum Einstieg die Seite bei Wikipedia empfohlen.


© 1999-2021 FHDW/Peter Baeumle-Courth. Document-Id: fhdwbap:opg:027892-3