Menu
Coddy logo textTech

Konstruktor-Initialisierungslisten

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 22 von 104.

Du hast die Doppelpunktsyntax in vorherigen Lektionen gesehen, etwa bei Player(std::string n, int h) : name(n), health(h) {}. Dies wird als Member-Initialisiererliste bezeichnet und ist die bevorzugte Methode, Member in C++ zu initialisieren.

Die Initialisierungsliste steht nach der Parameterliste des Konstruktors und beginnt mit einem Doppelpunkt. Jedes Mitglied wird direkt mit seinem Wert initialisiert, wobei die Einträge durch Kommas getrennt werden:

class Rectangle {
    int width;
    int height;
    const int id;
    int& reference;
public:
    Rectangle(int w, int h, int i, int& r) 
        : width(w), height(h), id(i), reference(r) {
        // Konstruktorrumpf (kann leer sein)
    }
};

Warum Initialisierungslisten anstelle von Zuweisungen im Konstruktorrumpf verwenden? Bei Zuweisungen werden Member zunächst standardmäßig konstruiert und anschließend neue Werte zugewiesen. Bei Initialisierungslisten werden Member direkt mit den korrekten Werten konstruiert – effizienter und manchmal erforderlich.

Bestimmte Member müssen mithilfe der Liste initialisiert werden:

  • const-Mitglieder – können nach der Konstruktion nicht zugewiesen werden
  • Referenzmitglieder – müssen bei der Initialisierung gebunden werden
  • Mitglieder ohne Standardkonstruktoren
class Player {
    const int maxHealth;    // Muss Initialisierungsliste verwenden
    std::string name;
public:
    // Das funktioniert
    Player(int max, std::string n) : maxHealth(max), name(n) {}
    
    // Das würde NICHT kompilieren:
    // Player(int max) { maxHealth = max; }  // Fehler!
};

Member werden in der Reihenfolge initialisiert, in der sie in der Klasse deklariert sind, nicht in der Reihenfolge der Initialisierungsliste. Schreibe deine Initialisierungsliste immer in der Reihenfolge der Deklarationen, um Verwirrung zu vermeiden.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Konfigurationssystem für eine Game-Engine, das zeigt, wann und warum Member-Initialisierungslisten unverzichtbar sind. Du erstellst eine GameConfig-Klasse mit Membern, die mithilfe der Syntax für Initialisierungslisten initialisiert werden müssen.

Du erstellst zwei Dateien, um deinen Code zu organisieren:

  • GameConfig.h: Definiere eine GameConfig-Klasse, die Spieleinstellungen speichert. Deine Klasse sollte Folgendes enthalten:
    • Ein const std::string gameName: der Titel des Spiels, der nach der Erstellung nicht geändert werden kann
    • Ein const int maxPlayers: die maximale Spieleranzahl, die bei der Konstruktion festgelegt wird
    • Ein int& difficultyRef: eine Referenz auf eine externe Schwierigkeitseinstellung
    • Ein int screenWidth und ein int screenHeight: reguläre Member für die Anzeigeeinstellungen
    • Einen Konstruktor, der alle erforderlichen Parameter übernimmt und jeden Member mithilfe der Initialisierungsliste initialisiert. Die Initialisierungsliste sollte der Reihenfolge folgen, in der die Member in der Klasse deklariert sind
    • Eine display()-Methode, die die Konfiguration in diesem Format ausgibt:
      Game: <gameName>
      Max Players: <maxPlayers>
      Difficulty: <difficultyRef value>
      Resolution: <screenWidth>x<screenHeight>
  • main.cpp: Lies Konfigurationswerte aus der Eingabe und erstelle ein GameConfig-Objekt. Du musst:
    • Den Spielnamen (String), die maximale Spieleranzahl (int), den Schwierigkeitsgrad (int), die Breite (int) und die Höhe (int) aus der Eingabe lesen: jeweils in einer eigenen Zeile
    • Eine lokale int-Variable für den Schwierigkeitsgrad erstellen, auf die die Konfiguration verweisen wird
    • Ein GameConfig-Objekt mithilfe des Konstruktors mit Initialisierungsliste erstellen
    • display() aufrufen, um die anfängliche Konfiguration anzuzeigen
    • Die Variable für den Schwierigkeitsgrad direkt ändern (sie mit 2 multiplizieren)
    • "After difficulty change:" ausgeben
    • display() erneut aufrufen, um zu zeigen, dass die Referenz den aktualisierten Wert widerspiegelt

Diese Aufgabe verdeutlicht, warum Initialisierungslisten wichtig sind: Deine const-Member und dein Referenz-Member können nicht im Konstruktorrumpf zugewiesen werden. Sie müssen in der Liste initialisiert werden. Der Referenz-Member zeigt außerdem, wie Änderungen an der ursprünglichen Variable durch das Konfigurationsobjekt widergespiegelt werden.

Binde deine Header-Datei in main.cpp mithilfe von #include "GameConfig.h" ein.

Probier es selbst

#include <iostream>
#include <string>
#include "GameConfig.h"

using namespace std;

int main() {
    // Eingabewerte lesen
    string gameName;
    getline(cin, gameName);
    
    int maxPlayers;
    cin >> maxPlayers;
    
    int difficulty;
    cin >> difficulty;
    
    int width;
    cin >> width;
    
    int height;
    cin >> height;
    
    // TODO: Erstelle ein GameConfig-Objekt mit dem Initialisierungslisten-Konstruktor
    // Der Konstruktor sollte empfangen: gameName, maxPlayers, difficulty (per Referenz), width, height
    
    // TODO: Rufe display() auf, um die Anfangskonfiguration anzuzeigen
    
    // TODO: Ändere die Variable difficulty direkt (multipliziere sie mit 2)
    
    // TODO: Print "After difficulty change:"
    
    // TODO: Rufe display() erneut auf, um die aktualisierte Konfiguration anzuzeigen
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C++-Compiler