Neler yeni

Yazılım Forum

Tüm özelliklerimize erişmek için şimdi bize katılın. Kayıt olduktan ve giriş yaptıktan sonra konu oluşturabilecek, mevcut konulara yanıt gönderebilecek, itibar kazanabilecek, özel mesajlaşmaya erişebilecek ve çok daha fazlasını yapabileceksiniz! Bu hizmetlerimiz ise tamamen ücretsiz ve kurallara uyulduğu sürece sınırsızdır, o zaman ne bekliyorsunuz? Hadi, sizde aramıza katılın!

C++'da Sınıflar ve Nesneler: Nesne Yönelimli Programlamanın Temelleri

Giriş: Nesne Yönelimli Programlamanın Kalbi

C++ modern programlama dillerinin temel taşlarından biridir ve güçlü bir nesne yönelimli programlama (NYP veya OOP) desteği sunar. NYP, gerçek dünya varlıklarını programlama dünyasına taşıyarak kodun daha anlaşılır, yönetilebilir ve yeniden kullanılabilir olmasını sağlar. Bu paradigmanın en temel yapı taşları ise 'sınıflar' ve 'nesneler'dir. Bu kapsamlı rehberde, C++'daki sınıfların ve nesnelerin ne olduğunu, nasıl tanımlandığını, kullanıldığını ve NYP'nin temel prensiplerini nasıl oluşturduğunu derinlemesine inceleyeceğiz.

Bir programın karmaşıklığı arttıkça, fonksiyonel yaklaşımlar yetersiz kalabilir. İşte bu noktada nesne yönelimli programlama devreye girer. Sınıflar ve nesneler, programcıların verileri ve bu veriler üzerinde işlem yapan fonksiyonları tek bir yapı altında birleştirmelerine olanak tanır. Bu sayede, yazılım geliştirme süreci daha modüler ve hataya açık olmayan bir hale gelir. Şimdi, bu iki anahtar kavramı daha yakından tanıyalım.

Sınıf Nedir?

Bir sınıf, gerçek dünyadaki bir varlığın veya soyut bir konseptin 'planı', 'şablonu' veya 'prototipi'dir. Kısacası, bir nesnenin nasıl görüneceğini ve nasıl davranacağını tanımlayan bir yapıdır. Bir sınıfın kendisi bir veri değildir; sadece nasıl veri oluşturulacağını gösteren bir kalıptır. Örneğin, bir 'Araba' sınıfı, arabaların genel özelliklerini (marka, model, renk, hız) ve davranışlarını (hızlanmak, yavaşlamak, durmak) tanımlar, ancak belirli bir arabayı temsil etmez.

Sınıflar, 'veri üyeleri' (attributes/properties) ve 'üye fonksiyonları' (methods/behaviors) adı verilen iki ana bileşenden oluşur. Veri üyeleri, nesnenin durumunu tutan değişkenlerdir; üye fonksiyonları ise nesnenin gerçekleştirebileceği eylemleri veya bu durumu manipüle eden operasyonları tanımlar.

"Bir sınıf, bir nesne oluşturmak için kullanılan bir kullanıcı tanımlı veri tipidir. Kendi veri üyelerine ve üye fonksiyonlarına sahiptir."

C++'da bir sınıfın temel yapısı şu şekildedir:
Kod:
class SinifAdi {
public:
    // Erişilebilir veri üyeleri ve üye fonksiyonları (metotlar)
    int publicVeri;
    void publicFonksiyon() {
        // Fonksiyonun gövdesi
    }

private:
    // Sadece sınıf içinden erişilebilir veri üyeleri ve üye fonksiyonları
    int privateVeri;
    void privateFonksiyon() {
        // Fonksiyonun gövdesi
    }

protected:
    // Sadece sınıf ve ondan türemiş sınıflar içinden erişilebilir
    int protectedVeri;
};

Yukarıdaki örnekte 'public', 'private' ve 'protected' anahtar kelimeleri 'erişim belirleyiciler' olarak adlandırılır. Bunlar, sınıfın üyelerine dışarıdan ne kadar erişilebileceğini kontrol eder. `public` üyeler her yerden erişilebilirken, `private` üyeler sadece sınıfın kendi içinden erişilebilir. `protected` üyeler ise sınıfın kendisinden ve o sınıftan türetilen diğer sınıflardan erişilebilir.

Nesne Nedir?

Bir nesne, bir sınıfın 'somut bir örneği'dir. Sınıf bir plan iken, nesne o plan kullanılarak inşa edilmiş gerçek bir varlıktır. Örneğin, 'Araba' sınıfı bir plandır; 'BMW 3 Serisi 2023 model beyaz araba' ise bu plandan türetilmiş somut bir nesnedir. Her nesne, kendi veri üyeleri kümesine sahiptir ve kendi üye fonksiyonlarını çağırabilir.

Nesneler bellek üzerinde yer kaplar ve bu bellek alanında kendi veri üyelerinin değerlerini saklar. Bir sınıfın birden çok nesnesini oluşturabilirsiniz ve her nesne birbirinden bağımsız olarak kendi durumunu korur.

Bir nesneyi oluşturmak (örneklemek) ve üyelerine erişmek oldukça basittir:
Kod:
#include <iostream>

class Araba {
public:
    std::string marka;
    std::string model;
    int hiz;

    void hizlan(int artis) {
        hiz += artis;
        std::cout << marka << " " << model << " hizlaniyor. Yeni hiz: " << hiz << std::endl;
    }

    void dur() {
        hiz = 0;
        std::cout << marka << " " << model << " durdu." << std::endl;
    }
};

int main() {
    Araba bmw;
    bmw.marka = "BMW";
    bmw.model = "3 Serisi";
    bmw.hiz = 0;
    bmw.hizlan(50);
    bmw.hizlan(30);
    bmw.dur();

    Araba mercedes;
    mercedes.marka = "Mercedes";
    mercedes.model = "C-Serisi";
    mercedes.hiz = 20;
    mercedes.hizlan(40);

    return 0;
}
Yukarıdaki örnekte, `Araba` sınıfından `bmw` ve `mercedes` adında iki farklı nesne oluşturduk. Her iki nesne de `marka`, `model` ve `hiz` gibi kendi bağımsız veri üyelerine sahiptir ve `hizlan` ve `dur` gibi kendi üye fonksiyonlarını çağırabilmektedir.

Kurucular (Constructors)

Kurucular, bir sınıfın nesnesi oluşturulduğunda otomatik olarak çağrılan özel üye fonksiyonlarıdır. Temel amaçları, yeni oluşturulan nesnenin veri üyelerine başlangıç değerleri atamak ve gerekli ilk ayarları yapmaktır. Bir kurucunun adı her zaman sınıfın adıyla aynıdır ve geri dönüş tipi (return type) yoktur.

Varsayılan Kurucu (Default Constructor): Parametre almayan kurucudur. Eğer bir sınıf için hiçbir kurucu tanımlamazsanız, C++ derleyicisi sizin için otomatik olarak boş bir varsayılan kurucu oluşturur.

Parametreli Kurucu (Parameterized Constructor): Nesne oluşturulurken dışarıdan değerler alarak veri üyelerini başlatmayı sağlayan kurucudur. Bu, nesnelerin daha kullanışlı ve özelleştirilebilir bir şekilde başlatılmasını sağlar.

Örnek:
Kod:
#include <iostream>
#include <string>

class Kedi {
public:
    std::string ad;
    int yas;

    // Varsayılan kurucu
    Kedi() {
        ad = "Bilinmiyor";
        yas = 0;
        std::cout << "Yeni bir kedi oluşturuldu (varsayılan)." << std::endl;
    }

    // Parametreli kurucu
    Kedi(std::string yeniAd, int yeniYas) {
        ad = yeniAd;
        yas = yeniYas;
        std::cout << ad << " adında, " << yas << " yaşında bir kedi oluşturuldu." << std::endl;
    }

    void miyavla() {
        std::cout << ad << " miyavliyor!" << std::endl;
    }
};

int main() {
    Kedi k1;
    k1.miyavla();

    Kedi k2("Tekir", 3);
    k2.miyavla();

    return 0;
}

Yıkıcılar (Destructors)

Yıkıcılar, bir nesne bellekten silindiğinde (kapsam dışına çıktığında veya `delete` ile silindiğinde) otomatik olarak çağrılan özel üye fonksiyonlarıdır. Kurucuların aksine, yıkıcılar parametre almaz ve geri dönüş tipleri yoktur. Adları sınıf adının önüne '~' (tilde) işareti eklenerek tanımlanır. Temel görevleri, nesnenin yaşam süresi boyunca ayrılmış olan dinamik belleği veya diğer sistem kaynaklarını serbest bırakarak bellek sızıntılarını önlemektir.

Örnek:
Kod:
#include <iostream>
#include <string>

class KaynakYoneticisi {
public:
    std::string kaynakAdi;

    KaynakYoneticisi(std::string ad) : kaynakAdi(ad) {
        std::cout << kaynakAdi << " kaynagi elde edildi." << std::endl;
    }

    ~KaynakYoneticisi() { // Yıkıcı
        std::cout << kaynakAdi << " kaynagi serbest birakildi." << std::endl;
    }
};

int main() {
    { // Yeni bir kapsam
        KaynakYoneticisi dosya("Ayarlar.txt");
        // 'dosya' nesnesi bu kapsamda yaşar.
    }
    // 'dosya' nesnesi kapsam dışına çıktığı için yıkıcısı çağrılır.

    KaynakYoneticisi veritabani("UrunlerVT");
    // Program sonlandığında 'veritabani' nesnesinin yıkıcısı çağrılır.

    return 0;
}

`this` İşaretçisi

`this` anahtar kelimesi, bir üye fonksiyonu içinde, o fonksiyonu çağıran nesnenin kendisine işaret eden bir işaretçidir. Özellikle bir üye fonksiyonunun parametre adıyla sınıfın veri üyesi adının çakıştığı durumlarda veya zincirleme metod çağrıları yapmak istendiğinde çok kullanışlıdır. `this` işaretçisi sayesinde, hangi değişkenin sınıf üyesi, hangisinin parametre olduğu açıkça belirtilebilir.

Örnek:
Kod:
#include <iostream>

class Dikdortgen {
public:
    int genislik;
    int yukseklik;

    Dikdortgen(int genislik, int yukseklik) {
        // Parametre adları ile üye değişken adları aynı.
        // 'this->' kullanarak üye değişkenlere erişiyoruz.
        this->genislik = genislik;
        this->yukseklik = yukseklik;
    }

    void bilgiGoster() {
        std::cout << "Genislik: " << this->genislik << ", Yukseklik: " << this->yukseklik << std::endl;
    }
};

int main() {
    Dikdortgen d(10, 20);
    d.bilgiGoster();
    return 0;
}

Kapsülleme (Encapsulation)

Kapsülleme, NYP'nin dört temel prensibinden biridir ve veriyi, o veri üzerinde işlem yapan fonksiyonlarla birlikte tek bir birim (sınıf) içinde paketlemek anlamına gelir. Ayrıca, bu prensip, bir nesnenin iç çalışma detaylarını dış dünyadan gizlemeyi ve verilere sadece tanımlanmış arayüzler (public metotlar) aracılığıyla erişilmesini sağlamayı hedefler. Bu sayede, sınıfın iç yapısında yapılan değişiklikler, dışarıdaki kodu etkilemez.

encapsulation_diagram.png

(Bu bir temsili görsel linkidir. Gerçek bir diyagram burada gösterilecektir.)

Kapsülleme, `private` ve `public` erişim belirleyicileri ile sağlanır. Genellikle, veri üyeleri `private` olarak tanımlanır ve bunlara erişim veya bunları değiştirmek için `public` 'getter' (erişici) ve 'setter' (değiştirici) metotları kullanılır. Bu, verilere doğrudan yetkisiz veya yanlış erişimi engeller, veri bütünlüğünü korur ve sınıfın kullanımını daha güvenli hale getirir.

  • Veri Güvenliği: Dışarıdan doğrudan erişimi engelleyerek verilerin yanlışlıkla değiştirilmesini önler.
  • Esneklik: Sınıfın iç implementasyonunu değiştirmeden, dış arayüzü koruyarak kodu güncellemeyi kolaylaştırır.
  • Modülerlik: Her sınıfın bağımsız bir birim olarak çalışmasını sağlar, bu da hata ayıklamayı ve bakımı kolaylaştırır.
  • Kullanım Kolaylığı: Kullanıcıların sınıfın karmaşık iç detaylarını bilmesine gerek kalmadan sadece public arayüzünü kullanarak etkileşimde bulunmasını sağlar.

Nesne Yönelimli Programlamanın Diğer Temelleri (Kısa Bir Bakış)

Sınıflar ve nesneler, NYP'nin yalnızca başlangıcıdır. Bu paradigmanın diğer önemli prensipleri şunlardır:

* Miras (Inheritance): Bir sınıfın (temel sınıf) özelliklerini ve davranışlarını başka bir sınıfa (türetilmiş sınıf) aktarmasıdır. Bu, kodun yeniden kullanılabilirliğini artırır. Daha fazla bilgi için C++ Miras Rehberi gibi kaynaklara göz atabilirsiniz.
* Çok Biçimlilik (Polymorphism): Farklı sınıflardaki nesnelerin aynı arayüze sahip olmasına rağmen farklı şekillerde davranabilme yeteneğidir. Bu, esnek ve genişletilebilir sistemler oluşturmak için kritik öneme sahiptir.
* Soyutlama (Abstraction): Karmaşık detayları gizleyerek sadece önemli bilgileri kullanıcılara sunma sürecidir. Sınıflar, soyutlamanın temel bir formudur.

Kapsamlı Bir C++ Sınıfı Örneği

Tüm bu kavramları bir araya getiren daha detaylı bir örnek verelim. Bir 'Kitap' sınıfı oluşturalım:

Kod:
#include <iostream>
#include <string>
#include <vector>

class Kitap {
private:
    std::string baslik;
    std::string yazar;
    int yayinYili;
    std::string isbn;
    std::vector<std::string> etiketler;
    bool oduncVerilebilir;

public:
    // Parametreli kurucu
    Kitap(std::string baslik, std::string yazar, int yayinYili, std::string isbn) {
        this->baslik = baslik;
        this->yazar = yazar;
        this->yayinYili = yayinYili;
        this->isbn = isbn;
        this->oduncVerilebilir = true; // Varsayılan olarak ödünç verilebilir
        std::cout << "Yeni kitap oluşturuldu: " << baslik << std::endl;
    }

    // Yıkıcı
    ~Kitap() {
        std::cout << baslik << " (ISBN: " << isbn << ") bellekten temizleniyor." << std::endl;
    }

    // Getter metotları (Kapsülleme için)
    std::string getBaslik() const { return baslik; }
    std::string getYazar() const { return yazar; }
    int getYayinYili() const { return yayinYili; }
    std::string getIsbn() const { return isbn; }
    bool isOduncVerilebilir() const { return oduncVerilebilir; }

    // Setter metotları (Gerekirse)
    void setOduncVerilebilir(bool durum) {
        oduncVerilebilir = durum;
    }

    // Etiket ekleme metodu
    void etiketEkle(const std::string& etiket) {
        etiketler.push_back(etiket);
        std::cout << baslik << " kitabina '" << etiket << "' etiketi eklendi." << std::endl;
    }

    // Kitap bilgilerini gösteren metot
    void bilgileriGoster() const {
        std::cout << "\n--- Kitap Bilgileri ---" << std::endl;
        std::cout << "Baslik: " << baslik << std::endl;
        std::cout << "Yazar: " << yazar << std::endl;
        std::cout << "Yayin Yili: " << yayinYili << std::endl;
        std::cout << "ISBN: " << isbn << std::endl;
        std::cout << "Odunc Verilebilir: " << (oduncVerilebilir ? "Evet" : "Hayir") << std::endl;
        std::cout << "Etiketler: ";
        if (etiketler.empty()) {
            std::cout << "Yok";
        } else {
            for (size_t i = 0; i < etiketler.size(); ++i) {
                std::cout << etiketler[i] << (i == etiketler.size() - 1 ? "" : ", ");
            }
        }
        std::cout << std::endl;
        std::cout << "-----------------------" << std::endl;
    }
};

int main() {
    // Kitap nesneleri oluşturma
    Kitap k1("Savas ve Baris", "Lev Tolstoy", 1869, "978-0140447935");
    k1.etiketEkle("Klasik");
    k1.etiketEkle("Rus Edebiyati");
    k1.bilgileriGoster();

    Kitap k2("Sapiens: Insanligin Kisa Bir Tarihi", "Yuval Noah Harari", 2011, "978-6050927892");
    k2.setOduncVerilebilir(false);
    k2.etiketEkle("Tarih");
    k2.etiketEkle("Bilim");
    k2.bilgileriGoster();

    // Nesnelerin kapsam dışına çıkması ve yıkıcıların çağrılması
    {
        Kitap geciciKitap("Kısa Ömürlü Kitap", "Yazar X", 2020, "123-456-7890");
        geciciKitap.bilgileriGoster();
    }
    // geciciKitap nesnesi burada yok edilecek

    std::cout << "\nProgram sonlaniyor..." << std::endl;
    return 0;
}
Bu örnek, bir sınıfın (Kitap) nasıl tanımlandığını, veri üyelerinin nasıl private tutulduğunu (kapsülleme), kurucuların nasıl kullanıldığını, üye fonksiyonlarının (getter/setter, etiket ekleme, bilgileri gösterme) nasıl çalıştığını ve yıkıcının ne zaman devreye girdiğini göstermektedir.

Sonuç

Sınıflar ve nesneler, C++'da nesne yönelimli programlamanın temelini oluşturur. Bu yapılar sayesinde, karmaşık sistemler daha küçük, yönetilebilir ve yeniden kullanılabilir parçalara ayrılabilir. Veri gizleme (kapsülleme), kod tekrarının azaltılması (miras) ve esnek tasarımlar (çok biçimlilik) gibi NYP prensipleri, sınıflar ve nesneler aracılığıyla hayata geçirilir. C++ ile güçlü ve sürdürülebilir yazılımlar geliştirmek için bu kavramları derinlemesine anlamak kritik öneme sahiptir.

Bu rehberin, C++'da sınıflar ve nesneler dünyasına sağlam bir giriş yapmanıza yardımcı olduğunu umuyoruz. İleri düzey C++ konularına geçmeden önce bu temelleri iyice kavramak, yazılım geliştirme yolculuğunuzda size büyük avantaj sağlayacaktır.
 
shape1
shape2
shape3
shape4
shape5
shape6
Üst

Bu web sitenin performansı Hazal Host tarafından sağlanmaktadır.

YazilimForum.com.tr internet sitesi, 5651 sayılı Kanun’un 2. maddesinin 1. fıkrasının (m) bendi ve aynı Kanun’un 5. maddesi kapsamında Yer Sağlayıcı konumundadır. Sitede yer alan içerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır.

YazilimForum.com.tr, kullanıcılar tarafından paylaşılan içeriklerin doğruluğunu, güncelliğini veya hukuka uygunluğunu garanti etmez ve içeriklerin kontrolü veya araştırılması ile yükümlü değildir. Kullanıcılar, paylaştıkları içeriklerden tamamen kendileri sorumludur.

Hukuka aykırı içerikleri fark ettiğinizde lütfen bize bildirin: lydexcoding@gmail.com

Sitemiz, kullanıcıların paylaştığı içerik ve bilgileri 6698 sayılı KVKK kapsamında işlemektedir. Kullanıcılar, kişisel verileriyle ilgili haklarını KVKK Politikası sayfasından inceleyebilir.

Sitede yer alan reklamlar veya üçüncü taraf bağlantılar için YazilimForum.com.tr herhangi bir sorumluluk kabul etmez.

Sitemizi kullanarak Forum Kuralları’nı kabul etmiş sayılırsınız.

DMCA.com Protection Status Copyrighted.com Registered & Protected