Eingeschlossene Objekte

Definition

Ein eingeschlossenes Objekt ist ein Objekt, welches Eigenschaft einer anderen Klasse ist. Es kann jedem beliebigen Klassentyp angehören, außer der sie umschließenden Klasse.

Das Einschließen von Objekten bietet sich immer an, 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).

#include <string>

// Eingeschlossene Klasse
class Color
{
    unsigned long color;
public:
    // ctor ohne Parameter
    Color(): color{0x808080UL}
    {}
};

// Umschliessende Klasse
class Window
{
    std::string title;  // Fenstertitel
    Color winColor;     // Eingeschlossenes Objekt
public:
    Window(std::string_view _title):
        title(_title)
        {}
};

int main()
{
    Window win1("1. Fenster");
}

Aufruf des Konstruktors

Besitzt der Konstruktor des eingeschlossenen Objekts Parameter, kann es auf zwei Arten initialisiert werden.

1. Fall: Wird das eingeschlossene Objekt immer mit den gleichen Daten initialisiert, kann es bei der Definition der umschließenden Klasse initialisiert werden.

#include <string>

// Eingeschlossene Klasse
class Color
{
    unsigned long color;
public:
    // ctor mit Parameter
    Color(unsigned long _color): color{_color}
    { }
};

// Umschliessende Klasse
class Window
{
    std::string title;          // Fenstertitel
    // Eingeschlossenes Objekt initialisieren
    Color winColor{0x808080UL};
public:
    Window(std::string_view _title):
        title(_title)
    { }
};

int main()
{
    Window win1("1. Fenster");
}

2. Fall: Hängt der Initialwert des eingeschlossenen Objekts von einem Parameter der umschließenden Klasse ab, wird der Konstruktor des eingeschlossenen Objekts in der Initialisiererliste des Konstruktors der umschließenden Klasse aufgerufen.

#include <string>

// Eingeschlossene Klasse
class Color
{
    unsigned long color;
public:
    // ctor mit Parameter
    Color(unsigned long _color): color{_color}
    { }
};

// Umschliessende Klasse
class Window
{
    std::string title;  // Fenstertitel
    Color winColor;     // Eingeschlossenes Objekt
public:
    Window(std::string_view _title, unsigned long color):
        title(_title), winColor(color)
    { }
};

int main()
{
    Window win1("1. Fenster",0x808080UL);
}

Zugriff auf Member

Der Zugriff auf die public-Member des eingeschlossenen Objekts aus Methoden der umschließenden Klasse heraus erfolgt in der Art, dass zuerst der Name des eingeschlossenen Objekts angegeben wird, dann der Punktoperator und anschließend das entsprechende Member.

Soll von außerhalb der umschließenden Klasse auf Member des eingeschlossenen Objekts zugegriffen werden, 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 Member der eingeschlossenen Klasse. Dieser Zugriff ist aber nur dann möglich, wenn das eingeschlossene Objekt und dessen Member public sind. Ist das eingeschlossene Objekt als private definiert, ist über das umschließende Objekt kein Zugriff auf das eingeschlossene Objekt möglich.

#include <string>

// Eingeschlossene Klasse
class Color
{
    unsigned long color;
public:
    // ctor ohne Parameter
    Color(): color(0x808080)
    {}
    inline void SetColor(unsigned long _color)
    {
        color = _color;
    }
};

// Umschliessende Klasse
class Window
{
    std::string title;  // Fenstertitel
public:
    Color winColor;     // Eingeschlossenes Objekt
    Window(std::string_view _title): title(_title)
    {
        winColor.SetColor(0x00);   // Fensterfarbe setzen
    }
};

int main()
{
    Window win1("1. Fenster");
    // Fensterfarbe setzen
    win1.winColor.SetColor(0xffffff);
}

Soll die Schnittstelle des eingeschlossenen Objekts nach außen hin verborgen werden, ist das eingeschlossene Objekt innerhalb der private-Sektion des umschließenden Objekts zu definieren. Um trotzdem auf das eingeschlossene Objekt zugreifen zu können, muss die umschließende Klasse hierfür eine eigene Schnittstelle zur Verfügung stellen. Auf diese Art und Weise kann z.B. die Schnittstelle des eingeschlossenen Objekts umdefiniert werden. Methoden, die die Schnittstelle eines anderen Objekts umdefinieren, werden auch als Adapter bezeichnet.

#include <string>

// Eingeschlossene Klasse
class Color
{
    unsigned long color;
public:
    // ctor ohne Parameter
    Color(): color(0x808080)
    {}
    // Color::SetColor erhaelt ulong-Wert
    inline void SetColor(unsigned long _color)
    {
        color = _color;
    }
};

// Umschliessende Klasse
class Window
{
    std::string title;  // Fenstertitel
    Color winColor;     // Eingeschlossenes Objekt
public:
    Window(std::string_view _title): title(_title)
    {
        winColor.SetColor(0x00);
    }
    // Window::Color erhaelt RGB-Werte und
    // uebergibt diese an Color::SetColor als ulong-Wert
    void SetColor(unsigned short red,unsigned short green,
                  unsigned short blue)
    {
        winColor.SetColor((red<<16)+(green<<8)+blue);

    }
};

int main()
{
    Window win1("1. Fenster");
    // Ruft Window::Color mit RGB-Werten auf
    win1.SetColor(0x40,0x80,0xc0);
}

Es 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 eine weitere Erläuterung diesbezüglich verzichtet.

Übungen

eobj_01:

Es ist eine Klasse zu erstellen, um die Namen, das Geburtsdatum und den Todestag von Komponisten abzuspeichern.

Da das Geburtsdatum und der Todestag die gleichen Eigenschaften besitzen, ist hierfür eine eigene Klasse zu erstellen. Die Datumsangaben sind als numerische Daten und nicht als String abzulegen.

Legen Sie die Daten folgender Komponisten ab:

Johann Sebastian Bach, *31.3.1685, +28.7.1750
Wolfgang Amadeus Mozart, *27.1.1756, +5.12.1791
Ludwig van Beethoven, *17.12.1770, +26.3.1827

Geben Sie Daten der Komponisten aus.

Name: Johann Sebastian Bach, *31.03.1685, +28.07.1750
Name: Wolfgang Amadeus Mozart, *27.01.1756, +05.12.1791
Name: Ludwig van Beethoven, *17.12.1770, +26.03.1827