Yıkıcıları Derinlemesine İnceleme
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 24 / 104.
Yıkıcı, bir nesne yok edildiğinde otomatik olarak çalışan özel bir üye işlevidir. Temel görevi, nesnenin ömrü 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ı, sınıfla aynı ada sahiptir ve başına bir tilde işareti ~ eklenir. 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:
- Yığın nesnelerin kapsamı sona erer
- Heap'te ayrılmış bir nesne üzerinde
deleteçağrılır - Geçici bir nesnenin yaşam süresi sona erer
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)Yapıcılardan farklı olarak, bir sınıfın yalnızca bir yıkıcısı olabilir. Onu aşırı yükleyemezsin.
Bir tane tanımlamazsan, derleyici özel bir şey yapmayan varsayılan bir yıkıcı oluşturur; yalnızca her ü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ı yazmalısın.
Görev
KolayEtkin kullanıcı oturumlarını takip eden ve nesneler yok edildiğinde, ister kapsam dışına çıksın ister açıkça silinsin, yıkıcıların kaynakları otomatik olarak nasıl temizlediğini gösteren bir oturum yöneticisi oluşturalım.
Kodunu düzenlemek için iki dosya oluşturacaksın:
Session.h: Dinamik olarak ayrılmış veriler içeren etkin bir kullanıcı oturumunu temsil eden birSessionsınıfı tanımla. Sınıfında şunlar bulunmalı:- Özel üyeler: bir
username(string), birsessionId(int) ve kullanıcı eylemlerini izleyenactivityLogadlı bir tamsayı dizisine işaretçi; ayrıca dizinin boyutu için birlogSize - Kullanıcı adı, oturum kimliği ve günlük boyutunu alan bir kurucu. Bu kurucu, etkinlik günlüğü dizisini heap belleğinde ayırmalı, tüm elemanları 0 olarak başlatmalı ve
"Session <sessionId> started for <username>"yazdırmalı - Ayrılmış belleği serbest bırakan ve
"Session <sessionId> ended for <username>"yazdıran bir yıkıcı - Etkinlik kodunu bir sonraki kullanılabilir slota kaydeden bir
logActivity(int activityCode)metodu (geçerli konumu dahili olarak takip et); günlük zaten doluysa çağrı yok sayılır, böylece sayı hiçbir zaman günlük boyutunu aşmaz - Kaç etkinliğin günlüğe kaydedildiğini döndüren bir
getActivityCount()metodu - Kullanıcı adını döndüren bir
getUsername()metodu
- Özel üyeler: bir
main.cpp: Farklı senaryolarda yıkıcıların davranışını göster. Girdiden bir kullanıcı adı ve günlük boyutu oku (her biri ayrı bir satırda), ardından:- Süslü parantezlerle
{ }bir kapsam bloğu oluştur ve bloğun içinde, girdi olarak verilen kullanıcı adı,101oturum kimliği ve girdi olarak verilen günlük boyutuyla stack üzerinde ayrılmış birSessionoluştur.1ve2kodlarıyla iki etkinlik kaydet, ardından"Stack session activities: <count>"yazdır. Blok sona erdiğinde yıkıcı otomatik olarak çalışmalı. - Bloktan sonra
"Stack session destroyed"yazdır newkullanarak heap belleğinde ayrılmış birSessionoluştur; kullanıcı adı"Guest", oturum kimliği202ve günlük boyutu3olsun.5koduyla bir etkinlik kaydet,"Heap session activities: <count>"yazdır, ardından nesneyi açıkçadeleteet.- Silme işleminden sonra
"Heap session destroyed"yazdır
- Süslü parantezlerle
Bu görev, yıkıcıların çağrılmasının iki temel yolunu gösterir: stack nesneleri kapsam dışına çıktığında otomatik olarak ve heap nesnelerini sildiğinde elle. Bellek sızıntılarını önlemek için her iki durumda da dinamik olarak ayrılmış etkinlik günlüğü düzgün şekilde serbest bırakılmalıdır.
#include "Session.h" kullanarak başlık dosyanı main.cpp dosyasına ekle.
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ü parantezlerle { } bir kapsam bloğu oluştur
// Bloğun içinde:
// - Girilen username, oturum ID'si 101 ve girilen günlük boyutuyla yığında ayrılmış bir Session oluştur
// - 1 ve 2 kodlu iki etkinliği kaydet
// - "Stack session activities: <count>" yazdır
// Blok sona erdiğinde yıkıcı otomatik olarak çalışır
// TODO: Bloktan sonra "Stack session destroyed" yazdır
// TODO: new kullanarak dinamik bellekte ayrılmış bir Session oluştur
// - Kullanıcı adı: "Guest", oturum ID'si: 202, günlük boyutu: 3
// - 5 kodlu bir etkinliği kaydet
// - "Heap session activities: <count>" yazdır
// - Oturumu sil
// TODO: Silme işleminden sonra "Heap session destroyed" yazdır
return 0;
}
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
1Nesne Yönelimli Programlamanın Temelleri
Harici DosyalarC++ Derleme ve Derleme SüreciHeader Dosyaları ve Kaynak DosyalarıNamespace'ler ve KapsamC++'ta Nesne Yönelimli Programlamaya GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriTekrar - Basit Hesap Makinesi4Sınıf Özellikleri
Nesne ve Statik ÜyelerGetter ve Setter'larconst Üye Fonksiyonlarımutable Anahtar SözcüğüStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim DüzeyleriCtor ve Dtor Çağrı SırasıMetot Geçersiz KılmaVirtual Fonksiyonlar ve VTableÇoklu KalıtımVirtual KalıtımÖzet - Çalışan Hiyerarşisi2Bellek Yönetimi
Stack ve Heap Belleğiİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++’ta Akıllı İşaretçilerC++’ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'ta Erişim BelirleyicileriErişim Belirleyicilerine Derinlemesine BakışBilgi GizlemeStruct ve Class Karşılaştırmasıİç İçe ve İç SınıflarTekrar - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme Zamanı ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDinamik Tür Dönüştürme ve RTTITekrar - Şekil Hesaplayıcı11İleri Düzey OOP Kavramları
Bileşim ve KalıtımCRTP ile Mixin'lerPimpl İdiomuTür SilmeEnum Sınıfları ve Güçlü TürlemeOOP'de İstisna YönetimiÖzel İstisna Hiyerarşileri14Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıBileşik KalıpBir Kalıp Olarak RAII3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopyalama YapıcısıTaşıma YapıcısıYapıcı Başlatma ListeleriYönlendiren YapıcılarYıkıcıları Derinlemesine İncelemeÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatörleri Aşırı YüklemeKarşılaştırma Operatörlerini Aşırı YüklemeAkış OperatörleriAtama Operatörünü Aşırı Yükleme[] ve () Operatörlerini Aşırı YüklemeTür Dönüşüm OperatörleriTekrar - Matrix Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeDeğişken Sayıda Argüman Alan ŞablonlarSFINAE ve Tür Özelliklerinin TemelleriTekrar: Genel Amaçlı KapsayıcıKendi başına pratik yap: Online C++ derleyicisi