C++ Kurs

Eingeschlossene Objekte

Die Themen:

Definition eines eingeschlossenen Objekts

Ein eingeschlossenes Objekt ist ein Objekt, welches in einer Klasse enthalten ist. Es kann jedem beliebigem Klassentyp angehören, außer natürlich der sie umschließenden Klasse. Das Einschließen von Objekten wird auch als Layering, Containment oder Embedding bezeichnet. Es bietet sich immer dann, wenn die Klassen zueinander eine hat-eine (has a) Beziehung haben. Im Beispiel hat das Fenster (die umschließende Klasse Window) eine Farbe (eingeschlossene Klasse Color).

PgmHeader
// Eingeschlossene Klasse
class Color
{
   ...
 public:
   Color(int col);
};
// Umschliessende Klasse
class Window
{
   Color winCol;     // Eingeschlossenes Objekt
   ...
};

Das Einschließen eines Objektes haben wir im Verlaufe des Kurses schon mehrfach angewandt, nämlich dann, wenn innerhalb einer Klasse ein string Objekt definiert wurde. Nun ja, im strengen Sprachgebrauch ist string eigentlich keine Klasse sondern nur ein typedef für das Klassen-Template basic_string<char>. Mehr zu Templates aber später noch.

Aufruf des Konstruktors eines eingeschlossenen Objekts

Benötigt der Konstruktor der Klasse des eingeschlossenen Objekts Parameter, so muss dessen Konstruktor in der Initialisiererliste des Konstruktors der umschließenden Klasse aufgerufen werden.

PgmHeader
// Eingeschlossene Klasse
class Color
{
   ...
 public:
   Color(int col);
};
// Umschliessende Klasse
class Window
{
   Color winCol;     // Eingeschlossenes Objekt
   ...
 public:
   Window (..., int col): winCol(col)
   {
      ...
   }
   ...
};

Nicht erlaubt ist es, das eingeschlossene Objekt bei seiner Definition bereits zu initialisieren, d.h. folgende Anweisung würde damit einen Übersetzungsfehler verursachen:

PgmHeader
// Eingeschlossene Klasse
class Color
{
   ...
 public:
   Color(int col);
};
// Umschliessende Klasse
class Window
{
   Color winCol(10);     // Das geht nicht!
   ...
};

Zugriff auf Member eines eingeschlossenen Objekts

Der Zugriff auf die public Member des eingeschlossenen Objekts aus Memberfunktionen der umschließenden Klasse heraus erfolgt in der Art, dass zuerst der Name des eingeschlossenen Objekts angegeben wird, dann folgt der Punktoperator und dann das entsprechende Member. Also genau so, wie ansonsten auf die public Member eines Objekts von außen zugegriffen wird.

Soll von außerhalb der umschließenden Klasse auf Member des eingeschlossenen Objekts zugegriffen werden, so erfolgt der Zugriff 'zweistufig'. D.h. zuerst wird der Name des umschließenden Objekts angegeben, dann der Name des eingeschlossenen Objekts und zum Schluss das gewünschte Member der eingeschlossenen Klasse. Dieser Zugriff ist allerdings nur dann möglich, wenn das eingeschlossene Objekt und dessen Member public sind. Ist das eingeschlossene Objekt als private definiert, kann über das umschließende Objekt kein Zugriff auf das eingeschlossene Objekt erfolgen.

PgmHeader
// Eingeschlossene Klasse
class Color
{
   ...
 public:
   void SetColor(...);
   ...
};
// Umschliessende Klasse
class Window
{
 public:
   Color winCol;
   Window();
   ...
};
// ctor der umschliessenden Klasse
Window::Window()
{
   ...
   winCol.SetColor(...);
}
// Fensterobjekt definieren
Window winObj;

// main() Funktion
int main()
{
   ...
   // Zugriff über äusseres Objekt
   winObj.winCol.SetColor(...);
   ...
}

Um die Schnittstelle des eingeschlossenen Objekts nach außen hin zu verbergen, ist das eingeschlossene Objekt innerhalb der private Sektion des umschließenden Objekts zu definieren. Soll der Zugriff auf das eingeschlossene Objekt trotzdem weiterhin erlaubt sein, so muss die umschließende Klasse hierfür eine eigene Schnittstelle zur Verfügung stellen. D.h. auf diese Art und Weise kann die Schnittstelle des eingeschlossenen Objekts umdefiniert werden. Solche Memberfunktionen, die die Schnittstelle eines anderen Objekts umdefinieren, werden auch als Adapter bezeichnet.

An dieser Stelle sei noch angemerkt, dass es auch möglich ist, eine Klasse (nicht ein Objekt!) in einer anderen Klasse einzuschließen. Da dieser Fall aber in der Praxis eher selten auftritt, wird auf hier auf eine weitere Erläuterung diesbezüglich verzichtet, um damit nicht noch völlige Verwirrung auszulösen.