Menu
Coddy logo textTech

Yıkıcılara Derinlemesine Bakış

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 24 / 104.

Bir yıkıcı (destructor), bir nesne yok edildiğinde otomatik olarak çalışan özel bir üye fonksiyondur. Temel görevi, nesnenin yaşam süresi boyunca edindiği dinamik olarak ayrılmış bellek, dosya tanıtıcıları veya ağ bağlantıları gibi kaynakları serbest bırakmaktır.

Yıkıcı metot (destructor), sınıf ile aynı ada sahiptir ve başına bir tilde ~ işareti getirilir. Hiçbir parametre almaz ve dönüş türü yoktur:

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";
    }
};

Yıkıcılar şu durumlarda otomatik olarak çağrılır:

  • Stack nesneleri kapsam dışına çıkar
  • Heap üzerinde ayrılmış bir nesne için delete çağrılır
  • Geçici bir nesnenin ömrü sona erer
void example() {
    FileHandler f1("data.txt", 100);    // Constructor çağrıldı
    
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // f2 için Destructor çağrıldı
    
}   // f1 için Destructor çağrıldı (kapsam dışına çıkıyor)

Yapıcıların aksine, bir sınıfın yalnızca bir yıkıcısı olabilir. Onu aşırı yükleyemezsiniz.

Eğer bir tane tanımlamazsanız, derleyici özel bir şey yapmayan varsayılan bir yıkıcı (destructor) oluşturur - sadece her bir üyeyi yok eder. Kaynakları yöneten sınıflar için, bellek sızıntılarını önlemek amacıyla kendi yıkıcınızı yazmalısınız.

challenge icon

Görev

Kolay

Aktif kullanıcı oturumlarını takip eden ve nesneler yok edildiğinde — ister kapsam dışına çıksınlar ister açıkça silinsinler — yıkıcıların (destructors) kaynakları nasıl otomatik olarak temizlediğini gösteren bir oturum yöneticisi oluşturalım.

Kodunuzu düzenlemek için iki dosya oluşturacaksınız:

  • Session.h: Dinamik olarak ayrılmış verilere sahip aktif bir kullanıcı oturumunu temsil eden bir Session sınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:
    • Özel (private) üyeler: bir username (string), bir sessionId (int) ve kullanıcı eylemlerini takip eden activityLog adında bir tam sayı dizisine işaret eden bir işaretçi (pointer) ve dizi boyutu için bir logSize
    • Kullanıcı adı, oturum kimliği ve günlük boyutu alan bir yapıcı (constructor). Bu yapıcı, etkinlik günlüğü dizisini yığında (heap) ayırmalı, tüm öğeleri 0'a eşitlemeli ve "Session <sessionId> started for <username>" yazdırmalıdır
    • Ayrılan belleği serbest bırakan ve "Session <sessionId> ended for <username>" yazdıran bir yıkıcı (destructor)
    • Etkinlik kodunu bir sonraki boş yuvaya kaydeden (mevcut konumu dahili olarak takip edin) bir logActivity(int activityCode) metodu
    • Kaç etkinliğin günlüğe kaydedildiğini döndüren bir getActivityCount() metodu
    • Kullanıcı adını döndüren bir getUsername() metodu
  • main.cpp: Farklı senaryolarda yıkıcı davranışını gösterin. Girişten bir kullanıcı adı ve günlük boyutu okuyun (her biri ayrı bir satırda), ardından:
    • Süslü parantezler { } kullanarak bir kapsam bloğu oluşturun ve içinde giriş yapılan kullanıcı adı, oturum kimliği 101 ve giriş yapılan günlük boyutu ile yığın üzerinde ayrılmış (stack-allocated) bir Session oluşturun. 1 ve 2 kodlarıyla iki etkinlik kaydedin, ardından "Stack session activities: <count>" yazdırın. Blok sona erdiğinde, yıkıcı otomatik olarak çalışmalıdır.
    • Bloktan sonra, "Stack session destroyed" yazdırın
    • new kullanarak "Guest" kullanıcı adı, 202 oturum kimliği ve 3 günlük boyutu ile yığında ayrılmış (heap-allocated) bir Session oluşturun. 5 koduyla bir etkinlik kaydedin, "Heap session activities: <count>" yazdırın, ardından bunu açıkça delete ile silin.
    • Silme işleminden sonra, "Heap session destroyed" yazdırın

Bu zorluk, yıkıcıların çağrılmasının iki ana yolunu gösterir: yığın nesneleri kapsamdan çıktığında otomatik olarak ve yığın (heap) nesnelerini sildiğinizde manuel olarak. Her iki yol da bellek sızıntılarını önlemek için dinamik olarak ayrılmış etkinlik günlüğünü düzgün bir şekilde serbest bırakmalıdır.

Başlık dosyanızı main.cpp içine #include "Session.h" kullanarak dahil edin.

Kopya kağıdı

Bir yıkıcı (destructor), bir nesne yok edildiğinde otomatik olarak çalışan özel bir üye fonksiyondur. Dinamik olarak ayrılmış bellek, dosya tanıtıcıları veya ağ bağlantıları gibi kaynakları serbest bırakır.

Yıkıcı, sınıf ile aynı isme sahiptir ve başına bir tilde ~ işareti alır. Parametre almaz ve geri dönüş tipi yoktur:

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";
    }
};

Yıkıcılar şu durumlarda otomatik olarak çağrılır:

  • Yığın (stack) nesneleri kapsam dışına çıktığında
  • Öbekte (heap) ayrılmış bir nesne üzerinde delete çağrıldığında
  • Geçici bir nesnenin ömrü sona erdiğinde
void example() {
    FileHandler f1("data.txt", 100);    // Yapıcı çağrıldı
    
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // f2 için yıkıcı çağrıldı
    
}   // f1 için yıkıcı çağrıldı (kapsam dışına çıkar)

Bir sınıfın yalnızca bir yıkıcısı olabilir (aşırı yükleme yapılamaz). Eğer bir tane tanımlamazsanız, derleyici varsayılan bir yıkıcı oluşturur. Kaynakları yöneten sınıflar için, bellek sızıntılarını önlemek amacıyla kendi yıkıcınızı yazmalısınız.

Kendin dene

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

using namespace std;

int main() {
    // Girdiyi oku
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: Süslü parantezler { } ile bir kapsam (scope) bloğu oluşturun
    // Bloğun içinde:
    //   - Giriş yapılan username, oturum ID'si 101 ve giriş yapılan log size ile yığın (stack) üzerinde ayrılmış bir Session oluşturun
    //   - 1 ve 2 kodlarıyla iki aktivite günlüğü (log) kaydedin
    //   - "Stack session activities: <count>" yazdırın
    // Blok sona erdiğinde, yıkıcı (destructor) otomatik olarak çalışır
    
    // TODO: Bloktan sonra, "Stack session destroyed" yazdırın
    
    // TODO: new kullanarak öbek (heap) üzerinde ayrılmış bir Session oluşturun
    //   - Username: "Guest", oturum ID: 202, log size: 3
    //   - 5 koduyla bir aktivite günlüğü (log) kaydedin
    //   - "Heap session activities: <count>" yazdırın
    //   - Oturumu silin (delete)
    
    // TODO: Silme işleminden sonra, "Heap session destroyed" yazdırın
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler