Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Zeiger und Operatorüberladung in C++: Ein Tutorial für das ContactBook-Projekt (Mai 2026)

Lerne, wie du mit Zeigern und Operatorüberladung in C++ ein effizientes Kontaktbuch erstellst – inspiriert von aktuellen Trends wie KI-gestützten Adressbüchern und Speicheroptimierung in Apps.

Zeiger C++ Operatorüberladung C++ ContactBook C++ COP3503C Lab 3 Zeiger und Referenzen C++ C++ Tutorial Deutsch Kontaktverwaltung C++ Speicher sparen mit Zeigern C++ Programmierung lernen Operatorüberladung Beispiele Dynamische Speicherverwaltung C++ C++ Klassen und Objekte Zeiger Array C++ Kopierkonstruktor C++ C++ Übungsaufgaben Kontaktbuch

Einleitung: Warum Zeiger und Operatorüberladung wichtig sind

Stell dir vor, du entwickelst eine App wie die neueste KI-gestützte Kontaktverwaltung, die auf deinem Smartphone und Laptop läuft. Jedes Gerät speichert eigene Kopien der Kontakte – das kostet Speicherplatz. Mit Zeigern in C++ kannst du Speicher sparen, indem du nur einmal pro Kontakt Speicher reservierst und von beiden Geräten darauf verweist. Die Operatorüberladung macht die Handhabung intuitiv: Statt umständlicher Methodenaufrufe schreibst du einfach buch1 += kontakt. In diesem Tutorial lernst du beides anhand eines ContactBook-Projekts – ähnlich wie bei COP3503C Lab 3.

Grundlagen: Arrays, Zeiger und Referenzen

Array-Deklaration und -Initialisierung

Ein Array ist eine Sammlung von Elementen gleichen Typs. In C++ muss die Größe zur Compile-Zeit bekannt sein. Beispiel:

const int MAX = 100;
int zahlen[MAX] = {0};

Der Zugriff erfolgt über den Index: zahlen[0] = 42;

Zeiger (Pointer)

Ein Zeiger speichert die Adresse einer Variable. Deklaration mit *:

int wert = 10;
int* ptr = &wert;  // ptr zeigt auf wert
cout << *ptr;      // Dereferenzierung: gibt 10 aus

Mit nullptr initialisieren, wenn kein gültiges Ziel vorhanden ist:

int* ptr = nullptr;

Der Pfeiloperator -> greift auf Member eines Objekts über einen Zeiger zu:

class Kontakt { public: string name; };
Kontakt* k = new Kontakt();
k->name = "Max";

Referenzen

Referenzen sind Alternativnamen für Variablen. Sie vermeiden Kopien und erlauben direkte Modifikation:

void aendere(int& x) { x = 5; }
int a = 3;
aendere(a);  // a ist jetzt 5

Rückgabe einer Referenz ermöglicht direkte Änderung des Rückgabewerts.

Das ContactBook-Projekt: Klassenstruktur

Das Projekt besteht aus zwei Klassen: Contact und ContactBook. Die ContactBook-Klasse speichert ein Array von Contact*-Zeigern. Dadurch teilen sich mehrere Geräte denselben Speicher für einen Kontakt.

Contact-Klasse

Enthält Name und Telefonnummer als string. Notwendige Methoden: Konstruktor, getName(), getNumber(), display().

class Contact {
private:
    string name;
    string nummer;
public:
    Contact(string n, string nr) : name(n), nummer(nr) {}
    string getName() const { return name; }
    string getNumber() const { return nummer; }
    void display() const {
        cout << name << ", " << nummer << endl;
    }
};

ContactBook-Klasse

Enthält ein statisches Array von Contact* (Größe z.B. 100) und einen Zähler für die aktuelle Anzahl. Methoden: find, add, addContacts, display, alphabetize, sowie überladene Operatoren.

class ContactBook {
private:
    static const int MAX = 100;
    Contact* kontakte[MAX];
    int anzahl;
public:
    ContactBook() : anzahl(0) {}
    // Weitere Methoden...
};

Wichtig: Die Klassen sind unabhängig, Contact wird nicht innerhalb von ContactBook definiert.

Operatorüberladung: Intuitive Syntax

Operatorüberladung erlaubt es, Operatoren wie +, +=, - für eigene Klassen zu definieren. Das macht den Code lesbarer. Im ContactBook-Projekt werden folgende Operatoren überladen:

  • += Contact – Einen Kontakt hinzufügen
  • += ContactBook – Alle Kontakte eines anderen Buches hinzufügen
  • + ContactBook – Zwei Bücher zusammenführen (neues Buch)
  • -= Contact – Einen bestimmten Kontakt entfernen
  • -= ContactBook – Alle Kontakte eines anderen Buches entfernen
  • - ContactBook – Differenz zweier Bücher (neues Buch)

Beispiel für += mit einem Kontakt:

ContactBook& operator+=(const Contact& c) {
    kontakte[anzahl++] = new Contact(c); // Kopie erstellen
    return *this;
}

Beachte: Wir erstellen eine Kopie des Kontakts, da c als Referenz übergeben wird. Der Zeiger im Array zeigt auf die Kopie.

Für += mit einem anderen ContactBook:

ContactBook& operator+=(const ContactBook& other) {
    for (int i = 0; i < other.anzahl; ++i) {
        kontakte[anzahl++] = new Contact(*other.kontakte[i]);
    }
    return *this;
}

Der +-Operator erzeugt ein neues Buch:

ContactBook operator+(const ContactBook& other) const {
    ContactBook ergebnis = *this;
    ergebnis += other;
    return ergebnis;
}

Ähnlich funktionieren die Minus-Operatoren, wobei find verwendet wird, um den zu entfernenden Kontakt zu lokalisieren.

Speicherverwaltung mit Zeigern

Jedes new benötigt ein delete. Im Destruktor der ContactBook-Klasse müssen alle dynamisch angelegten Kontakte gelöscht werden:

~ContactBook() {
    for (int i = 0; i < anzahl; ++i)
        delete kontakte[i];
}

Auch Kopierkonstruktor und Zuweisungsoperator müssen tiefe Kopien erstellen, um doppelte Löschungen zu vermeiden.

Praktische Anwendung: Speicher sparen wie in einer Cloud-App

Stell dir vor, du hast eine Cloud-basierte Kontakt-App, die auf mehreren Geräten läuft. Ohne Zeiger würde jedes Gerät eine eigene Kopie jedes Kontakts speichern – bei 1000 Kontakten à 1 KB sind das 1 MB pro Gerät. Mit Zeigern teilen sich alle Geräte denselben Speicher: nur 1 KB pro Kontakt insgesamt. Das spart Speicher und vereinfacht Synchronisation. Dieses Prinzip wird in vielen modernen Apps verwendet, z.B. in KI-gestützten Adressbüchern, die Kontakte aus verschiedenen Quellen zusammenführen.

Häufige Fehler und wie du sie vermeidest

  • Vergessen von delete: Führt zu Speicherlecks. Verwende einen Destruktor.
  • Flache Kopie: Standardmäßig kopiert der Kopierkonstruktor nur die Zeiger, nicht die Objekte. Implementiere eine tiefe Kopie.
  • Zeiger auf lokale Variable: Wenn du die Adresse einer lokalen Variable zurückgibst, wird sie nach Verlassen des Gültigkeitsbereichs ungültig.
  • Falsche Verwendung von new und delete: Jedes new muss genau ein delete haben.

Fazit

Mit Zeigern und Operatorüberladung hast du mächtige Werkzeuge, um effiziente und intuitive C++-Programme zu schreiben. Das ContactBook-Projekt zeigt, wie du Speicher sparst und gleichzeitig eine benutzerfreundliche Schnittstelle bereitstellst. Probiere es selbst aus – und denk daran: Übung macht den Meister. Viel Erfolg bei deinem Lab 3!