Menu
CoddyTech

Destruktor im Detail

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

Ein Destruktor ist eine spezielle Memberfunktion, die automatisch ausgeführt wird, wenn ein Objekt zerstört wird. Seine Hauptaufgabe besteht darin, Ressourcen freizugeben, die das Objekt während seiner Lebensdauer erworben hat, beispielsweise dynamisch zugewiesenen Speicher, Dateihandles oder Netzwerkverbindungen.

Der Destruktor hat denselben Namen wie die Klasse, mit einer Tilde ~ als Präfix. Er nimmt keine Parameter entgegen und hat keinen Rückgabetyp:

class FileHandler {
    std::string filename;
    int* buffer;
public:
    FileHandler(std::string name, size_t size) 
        : filename(name), buffer(new int[size]) {
        std::cout << "Opening " << filename << "\n";
    }
    ~FileHandler() {
        delete[] buffer;
        std::cout << "Closing " << filename << "\n";
    }
};

Destruktoren werden in diesen Situationen automatisch aufgerufen:

  • Stapelobjekte verlassen ihren Gültigkeitsbereich
  • delete wird für ein heap-allokiertes Objekt aufgerufen
  • Die Lebensdauer eines temporären Objekts endet
void example() {
    FileHandler f1("data.txt", 100);    // Konstruktor aufgerufen
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // Destruktor für f2 aufgerufen
}   // Destruktor für f1 aufgerufen (verlässt den Gültigkeitsbereich)

Im Gegensatz zu Konstruktoren kann eine Klasse nur einen Destruktor haben. Du kannst ihn nicht überladen.

Wenn du keinen definierst, erzeugt der Compiler einen standardmäßigen Destruktor, der nichts Besonderes tut – er zerstört einfach jedes Mitglied. Für Klassen, die Ressourcen verwalten, musst du deinen eigenen schreiben, um Speicherlecks zu verhindern.

challenge icon

Aufgabe

Einfach

Erstelle einen Sitzungsmanager, der aktive Benutzersitzungen verfolgt und demonstriert, wie Destruktoren Ressourcen automatisch bereinigen, wenn Objekte zerstört werden – unabhängig davon, ob sie ihren Gültigkeitsbereich verlassen oder explizit gelöscht werden.

Du erstellst zwei Dateien, um deinen Code zu organisieren:

  • Session.h: Definiere eine Session-Klasse, die eine aktive Benutzersitzung mit dynamisch zugewiesenen Daten darstellt. Deine Klasse sollte Folgendes enthalten:
    • Private Member: einen username (String), eine sessionId (Ganzzahl) und einen Zeiger auf ein Ganzzahl-Array namens activityLog, das Benutzeraktionen verfolgt, sowie eine logSize für die Arraygröße
    • Einen Konstruktor, der einen Benutzernamen, eine Sitzungs-ID und eine Protokollgröße entgegennimmt. Er soll das Aktivitätsprotokoll-Array auf dem Heap zuweisen, alle Elemente mit 0 initialisieren und "Session <sessionId> started for <username>" ausgeben
    • Einen Destruktor, der den zugewiesenen Speicher freigibt und "Session <sessionId> ended for <username>" ausgibt
    • Eine logActivity(int activityCode)-Methode, die den Aktivitätscode im nächsten verfügbaren Platz speichert (die aktuelle Position soll intern verfolgt werden); wenn das Protokoll bereits voll ist, wird der Aufruf ignoriert, sodass die Anzahl niemals die Protokollgröße überschreitet
    • Eine getActivityCount()-Methode, die zurückgibt, wie viele Aktivitäten protokolliert wurden
    • Eine getUsername()-Methode, die den Benutzernamen zurückgibt
  • main.cpp: Demonstriere das Verhalten von Destruktoren in verschiedenen Szenarien. Lies einen Benutzernamen und eine Protokollgröße aus der Eingabe ein (jeweils in einer eigenen Zeile), und führe anschließend Folgendes aus:
    • Erstelle mit geschweiften Klammern { } einen Gültigkeitsbereich und darin eine auf dem Stack angelegte Session mit dem eingegebenen Benutzernamen, der Sitzungs-ID 101 und der eingegebenen Protokollgröße. Protokolliere zwei Aktivitäten mit den Codes 1 und 2 und gib anschließend "Stack session activities: <count>" aus. Wenn der Block endet, soll der Destruktor automatisch ausgeführt werden.
    • Gib nach dem Block "Stack session destroyed" aus
    • Erstelle mit new eine auf dem Heap angelegte Session mit dem Benutzernamen "Guest", der Sitzungs-ID 202 und der Protokollgröße 3. Protokolliere eine Aktivität mit dem Code 5, gib "Heap session activities: <count>" aus und lösche sie anschließend explizit mit delete.
    • Gib nach dem Löschen "Heap session destroyed" aus

Diese Herausforderung zeigt die beiden wichtigsten Arten, wie Destruktoren aufgerufen werden: automatisch, wenn Stack-Objekte ihren Gültigkeitsbereich verlassen, und manuell, wenn du Heap-Objekte löschst. Beide Wege sollten das dynamisch zugewiesene Aktivitätsprotokoll ordnungsgemäß freigeben, um Speicherlecks zu verhindern.

Binde deine Header-Datei in main.cpp mit #include "Session.h" ein.

Probier es selbst

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

using namespace std;

int main() {
    // Eingabe lesen
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: Erstelle einen Scope-Block mit geschweiften Klammern { }
    // Innerhalb des Blocks:
    //   - Erstelle eine stack-allokierte Session mit dem Eingabe-Benutzernamen, der Session-ID 101 und der Eingabe-Log-Größe
    //   - Protokolliere zwei Aktivitäten mit den Codes 1 und 2
    //   - Print "Stack session activities: <count>"
    // Wenn der Block endet, wird der Destruktor automatisch ausgeführt
    
    // TODO: After the block, print "Stack session destroyed"
    
    // TODO: Erstelle eine heap-allokierte Session mit new
    //   - Benutzername: "Guest", Session-ID: 202, Log-Größe: 3
    //   - Protokolliere eine Aktivität mit Code 5
    //   - Print "Heap session activities: <count>"
    //   - Lösche die Session
    
    // TODO: After deletion, print "Heap session destroyed"
    
    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