C’den C++’a Geçerken: Nesne Yönelimli Programlamayı Anlamak
C++ ile Nesne Yönelimli Programlamayı Anlamak
42 Yolculuğumdan Notlar

Merhabalar 👋🏻
Kısa bir giriş notu: Konu anlatımı yorum satırından sonra başlayacaktır.
/*
Bir 42 öğrencisi olarak C dilinden C++’a geçiş yapıyorum. Fakat bu süreçte amacım C++ projelerini hızlıca yapıp teslim etmek değil; o projelerde kullanılan fikri gerçekten anlamak. Çünkü 42'nin öğrenme mantığında da sadece sonuca ulaşmak değil, o sonuca giderken yaşanan öğrenme yolculuğu da çok önemli.
Ben de bu öğrenme sürecini bir yazı serisi olarak kayıt altına almak istiyorum. Bu yüzden bu seri benim için bir çeşit öğrenme günlüğü olucak. C++’ı öğrenirken karşıma çıkan kavramları sadece ezberlemek yerine, anlamaya, sorgulamaya ve benimsemeye çalışacağım.
Bu seride Nesne Yönelimli Programlama konusunu, Feza Buzluca’nın İTÜ Bilgisayar Mühendisliği kapsamında hazırladığı Nesne Yönelimli Programlama ders notlarından referans alarak öğreneceğim. Aynı zamanda 42’deki C++ problemlerini çözerken, yalnızca alıştırmaları tamamlamaya değil; bu alıştırmaların arkasındaki düşünceyi, kullanılan programlama paradigmasını ve C++’ın bize kazandırmaya çalıştığı bakış açısını anlamaya odaklanacağım.
Kısacası bu seri “C++ öğreniyorum” diyen bir öğrencinin notları gibi başlıyacak. Ama hedefim yanlızca not tutmak değil; öğrendiğim bilgileri anlaşılır, konu odaklı ve öğretici bir şekilde yazıya dökmek olucak.
Umarım benim gibi C’den C++’a geçen, Nesne Yönelimli Programlama’yı ilk defa ciddi şekilde anlamaya çalışan ya da 42 C++ modüllerinden ilerleyen birine yol gösterir. */
Nesne Yönelimli Programlama yani Object-Oriented Programming — OOP bize yalnızca yeni bir sözdizimi öğretmez; problemi düşünme, modeli kurma ve yazılımı daha kaliteli hale getirme biçimi kazandırır. Yazılım kalitesi; anlaşılabilirlik, güvenilirlik, değiştirilebilirlik, yeniden kullanılabilirlik ve bakım kolaylığı gibi özelliklerle düşünülmelidir.
Bugün yazılım; sağlık, ulaşım, bankacılık, otomotiv, savunma, eğitim ve günlük hayatın neredeyse her alanında kullanılıyor. Bu yüzden kötü tasarlanmış bir yazılım yanlızca “bug” üretmez; ciddi maddi kayıplara, güvenlik problemerine hatta insan hayatını etkileyen sonuçlara yol açabilir. CrowdStrike, Boeing 737 Max olayları buna üzücü bir örnektir.
OOP’in Temel Fikri: Gerçek Dünyayı Yazılıma Yaklaştırmak
Gerçek dünya, yani problem alanı, nesnelerden oluşur. Yazılım sistemi yani çözüm alanı da nesnelerden oluşur. Bilgisayar programları gerçek dünya problemlerinin çözümünü oluşturan varlıkların bilgisayar ortamında ki temsillerini içerebilir.
Bir üniversite sistemi düşünelim. Bu sistemde öğrenciler, dersler, öğretim üyeleri, sınıflar, projeler ve notlar vardır. Eğer bu sistemi sadece fonksiyonlar üzerinden düşünürsek karmaşıklık hızla artar.
Ama nesne yönelimli bakarsak şunu sorarız:
Bu sistemde hangi nesneler var?
- Öğrenci
- Ders
- Öğretim üyesi
- Sınıf
- Proje
Bu nesnelerin sorumlulukları neler?
- Öğrenci not ortalamasını hesaplayabilir.
- Öğretim üyesi not girebilir.
- Ders belirli bir sınıfa atanabilir.
- Sınıf kapasitesini ve ders programını tutabilir.
Bu nesneler birbirleriyle nasıl ilişki kurar?
- Öğrenci ders alır.
- Ders öğretim üyesi tarafından verilir.
- Ders sınıfa atanır.
Bu yaklaşım, gerçek dünya ile yazılım modeli arasındaki mesafeyi azaltır. Ders notlarında bu fikir low representational gap olarak anlatılıyor. Yani problem dünyasındaki kavramlarla kod dünyasındaki kavramlar birbirine ne kadar yakınsa, yazılımı anlamak ve geliştirmek o kadar kolay olur.
Nesne Nedir ?
Gerçek dünya da nesnelerin iki temel yönü vardır :
- Attributes: özellikler, durum veya değişebilen karakteristikleri.
- Behavior: davranışlar, yetenekler veya sorumluluklar
Örneğin bir öğrenci nesnesi düşünelim.
Attributes:
- Numara — ID
- İsim — Name
- Doğum Tarihi — Birthdate
- Alınan derslerin listesi
Behavior:
- GPA hesaplamak
- Aldığı Dersleri listeleme
Yazılım tarafında ise bu yapı şöyle karşılık bulur:
- Özellikler -> data / member variables / attributes
- Davranışlar -> functions / methods / member functions
Yani bir yazılım nesnesi, veriler ile bu veriler üzerinde çalışan fonksiyonların bir araya gelmiş halidir.
Class ve Object Arasındaki Fark
Bir class programcı tarafından tanımlanan bir veri tipidir. Nesneleri tanımlamak için kullanılır.
- Class — Sınıf
- Object — Nesne
Bir Class:
- Bir plan veya şablon görevi görür.
- O sınıfa ait nesnelerde hangi veri ve fonksiyonların bulunucağını belirtir.
- Benzer nesnelerin ortak tanımıdır.
Bir class tanımı yapmak, doğrudan nesne oluşturmaz. Class yanlızca Object için bir plandır. Static üyeler hariç, classtan ayrıca object oluşturmak gerekir. Nesneler, sınıfların instance’larıdır. Yani sınıftan oluşturulan değişkenler veya sabitlerdir.
//C++'ta class tanımı şu şekilde yapılır
class ClassName
{
public:
//Class dışından erişilebilen üyeler
//Veri ve fonksiyonlar
private:
//Sınıf dışından erişilemeyen üyeler
//Veri ve fonksiyonlar
};
//Nesne Tanımlama Örnekleri
ClassName obj1{}, obj2{'A', 3.14}; // Otomatik Nesneler
ClassName *obj_ptr = new ClassName{}; //Dinamik Nesneler
class Point{
public:
void move(int newX, int newY);
void print() const;
bool isAtOrigin() const;
private:
int m_x{};
int m_y{};
}
Burada point sınıftır. point1 ve point2 ise bu sınıftan oluşturulmuş iki ayrı nesnedir. Her ikisi de aynı sınıftan gelir ama kendi verilerine sahiptir. Yani kısacası Class bir plan veya şablondur; object ise bu sınıfın bir örneğidir.
Nesne Örneği: Grafik Programında 2D Noktaları Tanımlayan Bir Model
Paydaşların gereksinimlerine göre noktaların şu özelliklere ve yeteneklere sahip olması gerekir:
Veri — Attributes
Noktaların x ve y koordinatları vardır. Gereksinimlere göre bu özellikleri temsil etmek için iki adet integer değişken kullanılabilir.
Davranış —Method
- Düzlem üzerinde hareket edebilir : move fonksiyonu
- Koordinatları ekrana yazdırabilir : print fonksiyonu
- Orijinde, yani (0, 0) noktasında olup olmadığını söyleyebilir: isAtOrigin fonksiyonu.
Point Class’ı şu şekilde tanımlanabilir :
class Point {
public:
void move(int, int);
void print() const;
bool isAtOrigin() const;
private:
int m_x{}, m_y{};
};
Bir sınıftaki veri ve fonksiyonlara, o sınıfın üyeleri denir. Yaygın kullanım olarak, member değişkenlerin isimlerinin başına m_ eklenir. Böylece bu değişkenler, fonksiyon parametrelerinden ve lokal değişkenlerden kolayca ayırt edilir.
Bu örnekte class içinde fonksiyonların yalnızca prototipleri, yani imzaları yazılmıştır. Fonksiyonların gövdeleri başka bölümlerinde ya da farklı dosyalarda bulunabilir. Eğer örnekte ki gibi class sınıfının içinde yazıldıysa bu fonksiyon inline function olarak tanımlanmış olur.
Encapsulation : Veri ve Davranışı Bir Araya Getirmek
OOP’nin en temel kavramlarından biri encapsulation, yani kapsüllemedir. Kapsülleme, bir nesneye ait verilerle o veriler üzerinden işlem yapan fonksiyonları aynı yapı içinde toplamaktır. Mesela yukarıda ki örnekte Point sınıfında koordinatlar ve koordinatları değiştiren fonksiyonlar aynı sınıf içinde tanımladık. Bu, kodu daha düzenli ve güvenli hale getirir.
Data Hiding: Her Şeyi Herkese Açmamak
Kapsülleme ile gelen diğer önemli kavram data hiding, yani veri gizlemedir. Bir sınıfın iç detayları dış dünyadan saklanmalıdır. Çünkü sınıfın kullanıcısı genellikle “bu sınıf içeride nasıl çalışıyor?” sorusuyla değil, “bu sınıf bana hangi hizmetleri sunuyor?” sorusuyla ilgilenir.
C++’ta bu ayrım genellikle şu erişim belirleyicilerle yapılır:
public:
//Dışarıdan erişilebilir arayüz
private:
//Sadece sınıfın kendi içinden erişilebilir detaylar
//Örneğin
class Point {
public:
bool move(int newX, int newY);
void print() const;
private:
int m_x;
int m_y;
};
Burada move() ve print() dışarıya açıktır. Ama m_x ve m_y gizlidir. Bunun en büyük faydası: Nesnenin verileri kontrolsüz şekilde değiştirilemez.
Mesela noktanın sadece belirli bir pencere içinde hareket etmesini istiyorsak:
bool Point::Move(int newX, int newY)
{
if(newX >= 0 && newX <= 500 &&
newY >= 0 && newY <= 300)
{
m_x = newX;
m_y = newY;
return true;
}
return false;
}
Bu durumda kullanıcı Point nesnesini pencere dışına taşıyamaz. Çünkü koordinatlar dışarıdan değiştirilemez.
Public Interface ve Private Implementation
Bir sınıfta iki dünya vardır:
Public Interface — Açık arayüz
Bu sınıfı kullanan kişinin gördüğü kısımdır. Yani “bu nesneyle ne yapabilirim ? “ sorusunun cevabıdır.
- Noktayı taşıyabilirim.
- Koordinatlarını yazdırabilirim.
- Başlangıç noktasında mı kontrol edebilirim.
Kullanıcının m_x ve m_y değerlerinin içeride nasıl tutulduğunu bilmesine gerek yoktur.
Point point1;
point1.move(100, 50);
point1.print();
if (point1.isAtOrigin()) {
// nokta başlangıç noktasında mı?
}
Private Implementation — Gizli gerçekleştirim
Bu ise sınıfın içeride nasıl çalıştığıdır. Sınıfı kullanan kişinin bunu bilmesi gerekmez. Bu ayrım yazılım kalitesi açısından önemlidir. Çünkü iç yapıyı değiştirdiğimizde, dış arayüz aynı kaldığı sürece sınıfı kullanan kodlar bozulmaz.
Yani burada Point nesnesi koordinatları nasıl saklıyor ? Şu an iki tane int değişkenle saklıyor.
/*class Point {
public:
bool move(int newX, int newY);
void print() const;*/
private:
int m_x;
int m_y;
};
Ama bu detay dışarıdan görünmez. Kullanıcı şunu yapamaz:
point1.m_x = 10; // Hata
point1.m_y = 20; // Hata
Çünkü m_x ve m_y private’tır.
Getter ve Setter: Kontrollü Erişim
Bazen private verileri dışarıdan okumak veya değiştirmek gerekebilir. Ama bu, verileri doğrudan public yapmak anlamına gelmez.
Bunun yerine özel public fonksiyonlar kullanılır:
- Getter/Accessor: Değeri okumak için kullanılır.
- Setter/Mutator: Değeri değiştirmek için kullanılır.
Örneğin:
int getX() const {
return m_x;
}
void setX(int newX){
if(newxX >= 0)
m_x = newX;
}
//////////////////
class Point {
public:
bool move(int newX, int newY);
void print() const;
bool isAtOrigin() const;
int getX() const;
int getY() const;
private:
int m_x{};
int m_y{};
};
Burada getX() sadece okuma yapar. setX() ise değer değiştirmeden önce kontrol eder. Yani sınıf kendi kurallarını korur. Dışarıya kontrollü bir erişim verilir, ama veri yine sınıfın içinde korunur.
const Member Function: “Ben Nesneyi Değiştirmiyorum” Demek
C++’ta bir member function sonuna const yazmak, o fonksiyonun nesnenin verilerini değiştirmeyeceğini belirtir.
Örneğin :
void print() const;
bool isAtOrigin() const;
Bu fonksiyonlar sadece bilgi verir, nesnenin durumunu değiştirmez. Bu neden önemli ?
Çünkü const nesneler üzerinde yanlıcaz const fonksiyonlar çağırabilir.
const Point fixedPoint;
fixedPoint.print(); // okey
fixedPoint.move(); //Hata
Burada fixedPoint sabit bir nesnedir. Bu yüzden onu taşıyamayız ama ekrana yazdırabiliriz.
Constructor: Nesnenin Doğru Başlamasını Sağlamak
Bir nesne oluşturulduğunda başlangıç değerlerinin doğru verilmesi gerekir. Eğer temel tipteki değişkenler başlatılmazsa rastgele anlamsız değerler içerebilir. Bu yüzden C++’ta constructor, yani kurucu fonksiyonlar kullanılır.
Ancak constructor’ı yalnızca “değişkenlere ilk değer veren fonksiyon” gibi düşünmek eksik olur. Evet constructor çoğu zaman bir nesnenin başlangıç değerini ayarlamak için kullanılır. Ancak asıl görevi daha geniştir: Bir nesneyi kullanılmaya başlamadan önce geçerli ve hazır bir duruma getirmek.
Point nesnesini düşünelim. Eğer point nesnesi değerleri başlatılmazsa, nesne rastgele ve anlamsız değerlerle başlayabilir. Constructor sayesinde her Point nesnesinin başlangıçta (0,0 ) gibi güvenli bir konumda başlamasını sağlayabiliriz.
class Point {
public:
Point();
private:
int m_x;
int m_y;
};
Point::Point()
{
m_x = 0;
m_y = 0;
}
Bu örnekte constructor, nesne oluşturulduğu anda otomatik çalışır ve koordinatları sıfırlar. Böylece Point point1; yazıldığında point1 nesnesi rastgele değerlerle değil, geçerli bir başlangıç durumuyla oluşur.
Ama constructor’ın gücü burada bitmez. Nesnenin çalışabilmesi için gereken daha büyük hazırlıklar da constructor içinde yapılabilir. Örneğin bir sınıf dinamik bellek kullanıyorsa constructor bu belleği ayırabilir. Bir sınıf dosya üzerinde çalışıyorsa constructor dosyayı açabilir. Bir sınıf uzak bir sistemle veya veritabanıyla çalışıyorsa constructor bağlantı kurabilir.
Yani constructor, nesnenin doğum anında yapılan hazırlık aşamasıdır. Nesne daha dış dünyaya açılmadan önce kendi içinde tutarlı, güvenli ve kullanılabilir hale getirir.
Bu bakış açısı özellikle C++ için çok önemlidir. Çünkü C++ programcıya bellek ve kaynak yönetimi konusunda büyük kontrol verir. Bu kontrol aynı zaman da sorumluluk getirir. Eğer bir nesne bir kaynak kullanıcaksa, o kaynağın doğru zamanda alınması ve nesne yok olurken doğru şekilde bırakılması gerekir. Constructor bu sürecin başlangıç noktasıdır.
Bu yüzden constructor için şöyle düşünebiliriz:
Constructor, nesnenin “hazırlık odasıdır”. Nesne sahneye çıkmadan önce gerekli tüm başlangıç işleri burada yapılır.
Bu başlangıç işi bazen koordinatları sıfırlamak kadar basit olabilir. Bazen bellek ayırmak, dosya açmak veya bağlantı kurmak kadar ciddi olabilir. Önemli olan şudur: Nesne oluşturulduğu anda eksik, bozuk veya kullanılamaz durumda olmamalıdır. Constructor, bunu garanti etmeye yarayan temel OOP araçlarından biridir.
Constructor’ın bazı özellikleri vardır:
- Sınıfla aynı adı taşır.
- Geri dönüş tipi yoktur.
- void bile yazılmaz.
- Nesne oluşturulurken otomatik çağırılır.
- Parametre alabilir.
- Bir sınıfta birden fazla constructor olabilir.
Default Constructor ve Parametreli Constructor
Parametre almadan çağrılabilen constructor’a default constructor denir.
Point point1;
Point point2{};
Bu iki kullanımda da default constructor çağrılır.
Ama bazen nesne oluşturulurken başlangıç değerlerini kullanıcı vermelidir:
class Point{
public:
Point(int x, int y);
private:
int m_x;
int m_y;
}
Artık şöyle nesneler oluşturabiliriz:
Point point1{10, 20};
Eğer sınıfta sadece parametreli constructor varsa, kullanıcı parametre vermeden nesne oluşturmaz.
Point point2; // Hata
Bu aslında sınıf tasarımcısının koyduğu bir kuraldır. Nesne geçerli bilgi olmadan oluşturulmasın isteniyorsa default constructor sunulmaz.
Member Initializer List: Nesne Oluşurken Başlatmak
Constructor içinde değer atamının iki yolu vardır.
Birincisi constructor gövdesinde atama yapmak:
Point::Poin(int x, int y)
{
m_x = x;
m_y = y;
}
İkincisi member initializer list, yani üye başlatma listesi kullanmaktır:
Point::Point(int x, int y)
: m_x{x}, m_y{y}
{
}
İkinci yöntem çoğu durumda daha doğru ve verimlidir. Çünkü değişken önce oluşturulup sonra atanmaz; doğrudan istenen değerle oluşturulur.
Özellikle const üyeler için member initializer list zorunludur:
class Point{
private:
const int MIN_x;
const int MIN_y;
public:
Point(int minX, minY)
: MIN_x{minX}, MIN_y{minY}
{
}
};
Çünkü const bir değişkene constructor gövdesinde sonradan değer atanmaz. Ve böylelikle sabit veri üyelerinin doğru başlatılması gerekmektedir.
Destructor: Nesne Biterken Temizlik Yapmak
Constructor nesnenin başlangıcını güvence altına alır. Bunun karşısında desthuctor, yani yıkıcı fonksiyon nesne yok edilirken otomatik çalışır.
Destructor özellikle şu durumlarda önemlidir:
- Dinamik bellek ayrıldıysa geri vermek,
- Dosya açıldıysa kapatmak,
- Ağ bağlantısı kurulduysa sonlandırmak,
- Sistem kaynağı kullanıldıysa temizlemek.
Destructor sınıf adıyla aynı adı taşır ama başında ~ bulunur:
class Strint{
public:
String(const char* text);
~String();
private;
char* m_contents;
}
Örneğin constructor içinde new ile bellek ayrıldıysa destructor içinde delete[] ile temizlenmelidir.
String::~String()
{
delete[] m_contents;
}
Bu fikir, c++’ta kaynak yönetiminin temelidir: Bir nesne bir kaynağı alıyorsa, o kaynak nesne yok olurken güvenli şekilde bırakılmalıdır.
Bitti
Bu yazıda Nesne Yönelimli Programlama’ya giriş yaparken class, object, encapsulation, data hiding, constructor ve destructor gibi temel kavramlara değindik. Elbette OOP bunlarla sınırlı değil. İlerleyen yazılarda inheritance, polymorphism, abstraction, operator overloading ve 42 C++ modüllerinde karşımıza çıkan diğer konu başlıklarını da adım adım incelemeye devam edeceğim.
Okuduğunuz için teşekkür ederim. Bir sonraki yazıda görüşmek üzere. 👋🏻
Ders notlarına buradan ulaşabilirsiniz.
메타데이터
- post_id
- 1b078a18940b
- slug
- cden-c-a-geçerken-nesne-yönelimli-programlamayı-anlamak-1b078a18940b
- url
- https://medium.com/@haticesena47/cden-c-a-ge%C3%A7erken-nesne-y%C3%B6nelimli-programlamay%C4%B1-anlamak-1b078a18940b
- canonical_url
- https://medium.com/@haticesena47/cden-c-a-ge%C3%A7erken-nesne-y%C3%B6nelimli-programlamay%C4%B1-anlamak-1b078a18940b
- author_url
- https://medium.com/@haticesena47
- status
- ok
- fetched_at
- 2026-06-09 15:37:30