C++ Constructor ve Destructor Mantığı
C++ constructor ve destructor kullanımını öğrenin. Nesne yaşam döngüsü, başlatma ve kaynak yönetimi örneklerle açıklanıyor.
C++’ta her sınıf, bir nesne oluşturulurken ve yok edilirken özel metotlara sahiptir: Constructor (kurucu) ve Destructor (yıkıcı). Constructor nesneyi ilk kullanıma hazır hale getirir, Destructor ise belleği temizler. Bu yapı, RAII (Resource Acquisition Is Initialization) prensibinin temelini oluşturur.
1. Constructor Nedir?
Constructor, bir sınıfın nesnesi oluşturulduğunda otomatik olarak çağrılan özel bir metottur. Amacı, değişkenleri başlatmak ve gerekli kaynakları hazırlamaktır.
- Adı sınıf adıyla aynı olmalıdır.
- Geri dönüş tipi (return type) olmaz.
- Overload (aşırı yükleme) yapılabilir.
class Book {
private:
string title;
int pages;
public:
// Varsayılan constructor
Book() {
title = "Bilinmeyen";
pages = 0;
cout << "Varsayılan constructor çağrıldı." << endl;
}
// Parametreli constructor
Book(string t, int p) {
title = t;
pages = p;
cout << "Parametreli constructor çağrıldı." << endl;
}
void Display() {
cout << "Kitap: " << title << " (" << pages << " sayfa)" << endl;
}
};
Nesne oluşturulduğunda constructor otomatik çalışır:
int main() {
Book b1;
Book b2("C++ Programlama", 900);
b1.Display();
b2.Display();
}
2. Destructor Nedir?
Destructor, nesne ömrü sona erdiğinde çağrılan özel metottur. Belleği serbest bırakmak, dosyaları kapatmak gibi temizlik işlemleri için kullanılır.
- Adı sınıf adıyla aynıdır, ancak başında
~(tilde) bulunur. - Parametre almaz, overload edilemez.
class Book {
public:
Book() {
cout << "Constructor çalıştı." << endl;
}
~Book() {
cout << "Destructor çalıştı." << endl;
}
};
int main() {
Book b;
} // main bitince destructor otomatik çağrılır
Çıktı:
Constructor çalıştı.
Destructor çalıştı.
Destructor otomatik çağrıldığı için manuel olarak çağrılmamalıdır.
3. Book Örneği: Genişletilmiş Constructor ve Destructor
Şimdi Book sınıfını daha gerçekçi hale getirelim. İçinde dinamik olarak ayrılmış veriler bulunsun (örneğin kitap açıklaması). Böylece destructor’ın neden önemli olduğunu görebiliriz.
#include <iostream>
#include <string>
using namespace std;
class Book {
private:
string title;
int pages;
string *description; // Dinamik bellek
public:
// Constructor
Book(string t, int p, string d)
: title(t), pages(p) {
description = new string(d);
cout << "Book constructor: " << title << endl;
}
// Destructor
~Book() {
cout << "Book destructor: " << title << endl;
delete description; // Dinamik bellek serbest bırakılır
}
void Display() const {
cout << "Kitap: " << title << " (" << pages << " sayfa)" << endl;
cout << "Açıklama: " << *description << endl;
}
};
int main() {
Book b1("1984", 328, "Distopik bir roman.");
b1.Display();
}
Çıktı:
Book constructor: 1984
Kitap: 1984 (328 sayfa)
Açıklama: Distopik bir roman.
Book destructor: 1984
Destructor, nesne main()’in sonunda yaşam döngüsünü tamamladığında çağrılır
ve new ile ayrılmış belleği geri serbest bırakır.
4. Constructor Overloading (Aşırı Yükleme)
Aynı sınıfta birden fazla constructor tanımlanabilir. Parametre sayısına göre uygun olan çağrılır.
class Book {
private:
string title;
int pages;
public:
Book() : title("Bilinmeyen"), pages(0) {}
Book(string t) : title(t), pages(100) {}
Book(string t, int p) : title(t), pages(p) {}
void Display() {
cout << "Kitap: " << title << " (" << pages << " sayfa)" << endl;
}
};
int main() {
Book b1;
Book b2("C++ 101");
Book b3("Design Patterns", 450);
b1.Display();
b2.Display();
b3.Display();
}
5. Copy Constructor (Kopya Kurucu)
Varsayılan olarak C++ bir copy constructor oluşturur, ancak dinamik bellek kullanıyorsak kendi kopya constructor’ımızı tanımlamalıyız.
class Book {
private:
string title;
string *desc;
public:
Book(string t, string d) {
title = t;
desc = new string(d);
cout << "Constructor: " << title << endl;
}
// Kopya constructor
Book(const Book &other) {
title = other.title;
desc = new string(*other.desc); // derin kopya
cout << "Copy constructor: " << title << endl;
}
~Book() {
delete desc;
cout << "Destructor: " << title << endl;
}
void Display() {
cout << title << " - " << *desc << endl;
}
};
int main() {
Book b1("C++ Primer", "Temel seviye kılavuz");
Book b2 = b1; // copy constructor çağrılır
b2.Display();
}
Derin kopyalama (deep copy) yapılmazsa iki nesne aynı belleği paylaşır, bu da destructor çağrıldığında “çifte delete” hatasına neden olur.
6. Book Sistemi – Yaşam Döngüsü Takibi
Aşağıdaki örnek, bir kitap nesnesinin oluşturulma ve yok edilme sırasını gösterir. Bu, constructor ve destructor’ın gerçek yaşam döngüsünü anlamak için idealdir.
#include <iostream>
#include <string>
using namespace std;
class Author {
public:
Author(string n) { cout << "Author oluşturuldu: " << n << endl; }
~Author() { cout << "Author yok edildi." << endl; }
};
class Book {
private:
string title;
Author author;
public:
Book(string t, string a) : title(t), author(a) {
cout << "Book oluşturuldu: " << title << endl;
}
~Book() {
cout << "Book yok edildi: " << title << endl;
}
};
int main() {
Book b("Hayvan Çiftliği", "George Orwell");
}
Çıktı:
Author oluşturuldu: George Orwell
Book oluşturuldu: Hayvan Çiftliği
Book yok edildi: Hayvan Çiftliği
Author yok edildi.
Gördüğünüz gibi önce Author constructor’ı çağrılır,
ardından Book constructor’ı.
Yok edilirken tam tersi sıra uygulanır (önce Book, sonra Author).
Bu, composition (bileşim) ilişkilerinde C++’ın yaşam döngüsü sırasını gösterir.
7. TL;DR
- Constructor → Nesne oluşturulurken otomatik çağrılır.
- Destructor → Nesne yaşam döngüsü bittiğinde otomatik çağrılır.
- Constructor overload edilebilir, Destructor edilemez.
- Dinamik bellek varsa Destructor mutlaka
deleteçağırmalıdır. - Copy constructor derin kopya (deep copy) yapmalıdır.
- Oluşturulma sırası: önce alt bileşenler, sonra sınıf; Yok edilme sırası: önce sınıf, sonra alt bileşenler.
- Tüm örnekler Visual Studio 2022 veya GCC 11+ ortamında çalıştırılabilir.
İlişkili Makaleler
C++ Bellek Sızıntıları ve Valgrind ile Analiz
C++’ta bellek sızıntılarını tespit etmeyi ve Valgrind ile analiz yapmayı öğrenin. Bellek hatalarını örneklerle giderin.
C++ Copy Constructor ve Assignment Operator
C++ copy constructor ve assignment operator kullanımını öğrenin. Kopyalama semantiği ve nesne yönetimi örneklerle anlatılıyor.
C++ Dinamik Bellek Yönetimi: new ve delete
C++’ta new ve delete ile dinamik bellek yönetimini öğrenin. Bellek ayırma, serbest bırakma ve güvenli kullanım örneklerle anlatılıyor.
C++ Scope (Kapsam) ve Yaşam Döngüsü
C++’ta scope ve yaşam döngüsünü öğrenin. Değişken erişimi, kapsam kuralları ve nesne ömrü örneklerle anlatılıyor.
C++ Smart Pointer'lara Giriş
C++ smart pointer'larını öğrenin. unique_ptr, shared_ptr ve weak_ptr ile güvenli bellek yönetimi ve modern C++ tekniklerini keşfedin.
C++ this Pointer Nedir?
C++ this pointer kullanımını öğrenin. Nesnenin kendi örneğine erişim, metot zincirleme ve sınıf tasarımı örneklerle anlatılıyor.
C++'ta Sınıflara (Class) Giriş
C++’ta class kavramını öğrenin. Sınıf tanımlama, nesne oluşturma, üyeler ve nesne yönelimli programlamanın temelleri örneklerle anlatılıyor.