Menu
Coddy logo textTech

Destruktoren im Detail

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

Ein Destruktor ist eine spezielle Elementfunktion, 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, wie z. B. dynamisch zugewiesener Speicher, Dateihandles oder Netzwerkverbindungen.

Der Destruktor hat denselben Namen wie die Klasse, vorangestellt mit einer Tilde ~. 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:

  • Stack-Objekte verlassen den Gültigkeitsbereich
  • delete wird für ein auf dem Heap alloziertes 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. Sie können ihn nicht überladen.

Wenn Sie keinen definieren, generiert der Compiler einen Standard-Destruktor, der nichts Besonderes tut – er zerstört einfach jedes Element. Für Klassen, die Ressourcen verwalten, müssen Sie einen eigenen schreiben, um Speicherlecks zu verhindern.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Sitzungsmanager erstellen, der aktive Benutzersitzungen verfolgt und demonstriert, wie Destruktoren Ressourcen automatisch bereinigen, wenn Objekte zerstört werden — unabhängig davon, ob sie den Gültigkeitsbereich verlassen oder explizit gelöscht werden.

Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:

  • Session.h: Definieren Sie eine Session-Klasse, die eine aktive Benutzersitzung mit dynamisch zugewiesenen Daten darstellt. Ihre Klasse sollte Folgendes enthalten:
    • Private Member: einen username (string), eine sessionId (int) und einen Zeiger auf ein Integer-Array namens activityLog, das Benutzeraktionen verfolgt, zusammen mit einer logSize für die Array-Größe
    • Einen Konstruktor, der einen Benutzernamen, eine Sitzungs-ID und eine Protokollgröße entgegennimmt. Er sollte das activity log-Array auf dem Heap reservieren, alle Elemente mit 0 initialisieren und "Session <sessionId> started for <username>" ausgeben
    • Einen Destruktor, der den reservierten Speicher freigibt und "Session <sessionId> ended for <username>" ausgibt
    • Eine logActivity(int activityCode)-Methode, die den Aktivitätscode im nächsten verfügbaren Slot speichert (verfolgen Sie die aktuelle Position intern)
    • Eine getActivityCount()-Methode, die zurückgibt, wie viele Aktivitäten protokolliert wurden
    • Eine getUsername()-Methode, die den Benutzernamen zurückgibt
  • main.cpp: Demonstrieren Sie das Verhalten des Destruktors in verschiedenen Szenarien. Lesen Sie einen Benutzernamen und eine Protokollgröße von der Eingabe ein (jeweils in einer separaten Zeile), dann:
    • Erstellen Sie einen Scope-Block mit geschweiften Klammern { } und erstellen Sie darin eine Stack-allozierte Session mit dem eingegebenen Benutzernamen, der Sitzungs-ID 101 und der eingegebenen Protokollgröße. Protokollieren Sie zwei Aktivitäten mit den Codes 1 und 2, und geben Sie dann "Stack session activities: <count>" aus. Wenn der Block endet, sollte der Destruktor automatisch ausgeführt werden.
    • Geben Sie nach dem Block "Stack session destroyed" aus
    • Erstellen Sie eine Heap-allozierte Session mit new, dem Benutzernamen "Guest", der Sitzungs-ID 202 und der Protokollgröße 3. Protokollieren Sie eine Aktivität mit dem Code 5, geben Sie "Heap session activities: <count>" aus und löschen Sie sie dann explizit mit delete.
    • Geben Sie nach dem Löschen "Heap session destroyed" aus

Diese Herausforderung zeigt die zwei Hauptwege, auf denen Destruktoren aufgerufen werden: automatisch, wenn Stack-Objekte ihren Gültigkeitsbereich verlassen, und manuell, wenn Sie Heap-Objekte löschen. Beide Pfade sollten das dynamisch allozierte Aktivitätsprotokoll ordnungsgemäß freigeben, um Speicherlecks zu vermeiden.

Binden Sie Ihre Header-Datei in main.cpp mit #include "Session.h" ein.

Spickzettel

Ein Destruktor ist eine spezielle Elementfunktion, die automatisch ausgeführt wird, wenn ein Objekt zerstört wird. Er gibt Ressourcen wie dynamisch zugewiesenen Speicher, Dateihandles oder Netzwerkverbindungen frei.

Der Destruktor hat denselben Namen wie die Klasse, ergänzt um eine vorangestellte Tilde ~. 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 automatisch aufgerufen, wenn:

  • Stack-Objekte den Gültigkeitsbereich verlassen
  • delete für ein auf dem Heap alloziertes Objekt aufgerufen wird
  • 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)

Eine Klasse kann nur einen Destruktor haben (kein Überladen). Wenn Sie keinen definieren, generiert der Compiler einen Standard-Destruktor. Für Klassen, die Ressourcen verwalten, müssen Sie einen eigenen schreiben, um Speicherlecks zu vermeiden.

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-allozierte Session mit dem eingegebenen username, der session ID 101 und der eingegebenen log size
    //   - Protokolliere zwei Aktivitäten mit den Codes 1 und 2
    //   - Gib "Stack session activities: <count>" aus
    // Wenn der Block endet, wird der Destruktor automatisch ausgeführt
    
    // TODO: Gib nach dem Block "Stack session destroyed" aus
    
    // TODO: Erstelle eine Heap-allozierte Session mit new
    //   - Username: "Guest", session ID: 202, log size: 3
    //   - Protokolliere eine Aktivität mit dem Code 5
    //   - Gib "Heap session activities: <count>" aus
    //   - Lösche die Session mit delete
    
    // TODO: Gib nach dem Löschen "Heap session destroyed" aus
    
    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