Yazan: Yrd. Doç. Dr. Şadi Evren ŞEKER

Bu yazının amacı, C++ dili üzerinden, nesne yönelimli programlamaya hızlı bir başlangıç yapmaktır. Yazı, C dilini bilen kişileri hedef alarak hazırlanmıştır.

C++ dili, gelişimi itibariyle, C dilinin bir devamı niteliğindedir ve C dilinde bulunan bütün özellikleri desteklemek gibi bir problemli bulunur. Bu problem, C++ dilinin tam olarak nesne yönelimli (pure object oriented) olmasını engellemiştir. Bu anlamda C++ dilinin nesne yönelimli olması konusunda sıkıntıları bulunur. Örneğin JAVA dili, bu anlamda çok daha iyi bir tercih olabilir. Elbette C++ dilinin de bu yazının amacı dışında kalan pek çok avantajı bulunmaktadır.

Öncelikle nesne yönelimli programlama mantığını anlamak için, nesne yönelimli programlama öncesini hatırlayalım.

Yapısal olmayan programlama

Günümüzde, nesne yönelimli bütün programlama dilleri, yapısal programlama özelliklerini de taşır. Ancak yapısal programlama (structured programming) öncesindeki programlama dillerinde, fonksiyonlar bulunmaz. Basitçe her program tek bir akıştan ibarettir.

Bu durum, C dilindeki tek bir main fonksiyonu ile yazılmış program olarak düşünülebilir. İlave hiçbir fonksiyonun olmadığı kodlardır.

Prosedürle Programlama

Yapısal programlama olarak da kabul edebileceğimiz bu programlama mantığında, bir ana fonksiyon (örneğin main fonksiyonu) olduğu gibi, ilave fonksiyonlarla kod desteklenebilir.

Bu durumda, programın akışı bazı durumlarda farklı parametrelerle, kodun farklı kısımlarına atlayabilir.

Buradaki parametrize edilebilirlik çok önemlidir ve fonksiyonel (prosedürle) programlamanın temelini oluşturur.

Örneğin sayıların üstünü hesaplayan bir fonksiyonu bir kere yazmak ve ardından gereken her taban ve üst için bu fonksiyonu çağırmak kodlamayı da koda yapılan müdahaleleri de kolaylaştırır.

Örneğin, yukarıdaki şekilde görüldüğü üzere, ana akış, çeşitli yerlerde, fonksiyona gidip sonra kaldığı yerden devam edebilir.

Bu programlama yaklaşımında ne yazık ki tek bir ana programdan ve bu ana programın fonksiyonlarından bahsetmek mümkündür. Programın alt parçalara bölünmesi ve her parçanın kendine özgü veri ve fonksiyonlarla tasarlanması mümkün olmaz.

Modüler Programlama

Bu programlama yaklaşımında, bir projenin birden fazla modüle bölünmesi söz konusudur. C programlama dili için, projenin birden fazla dosyaya bölünmesi olarak düşünülebilir. Örneğin her modül için ayrı bir .h (header dosyası) ve .c ( kaynak kodu) bulunduğunu düşünelim, bu durumda her modül, kendi fonksiyonlarına ve verilerine sahip olacaktır.

Bu çözüm, nesne yönelimli programlamaya yakın görülse bile, programlama sırasında her modül için tek bir çalışan örnekten bahsedilebilir.

Örneğin, bir firmada, çalışan kişilerin bilgilerinin tutulduğu ve bu bilgiler üzerinde işlem yapıldığını düşünelim. Kişi bilgilerimizi saklamak için bir modül tasarlayacak ve kişiler ile ilgili verileri ve fonksiyonları bu modülde kodlayacağız.

Buraya kadar her şey normal görülse de, programımızda sadece tek bir kişi hafızaya yüklü olabilecektir. Modüler programlamada aynı anda, birden fazla kişinin hafızaya yüklü olması, değişken olarak mümkün olsa da, fonksiyonel olarak mümkün olamaz. Örneğin bir kişinin üzerinde işlem yapılıp bitirildikten sonra, diğer bir kişinin üzerindeki işleme başlanabilir.

Kısacası, çalışan programımızın, her modül için tek bir durumu (state) bulunmalıdır.

Diğer bir problem de, hafızanın verimli kullanılmasıdır. Örneğin her modül için hafızada gerekli olan değişkenler kadar yer kaplandıktan sonra, bu yerin yönetiminin programcı tarafından, dikkatli bir şekilde yapılması beklenir. Modülde bulunan göstericiler (pointers) için hafıza ayrımı (malloc) yapıldığı gibi bu hafızanın kullanımı bittikten sonra da hafızadan kaldırılması gerekir (free).

Nesne Yönelimli Programlama

Nesne yönelimi programlama, yukarıda anlatılan bütün özellikleri desteklemenin yanında, programlanmak üzere sınıf (class) ve nesne (object) özelliklerini eklemiştir. Bu eklenti ile, nesneler, sınıflardan türetilmekte ve bu sayede hafızda (ram) sadece nesneler bulunmaktadır. Her nesne kendine özgü fonksiyonlar ve veriler taşımanın yanında kendi hafıza yönetimini yapar ve kendi durumunu saklar.

Modüler programlamadaki örneğe dönecek olursak, hafızada aynı anda birden fazla kişi ve her kişinin fonksiyonlarının farklı çalışma durumları bulunabilir.

Nesne yönelimli programlama da kullanılan terminolojiye geçecek olursak, fonksiyonlar metot (method) ve veriler de özellik (property) olarak isimlendirilir. Aslında işlevsellik anlamında bir fark bulunmamasına rağmen, bu isimlendirme, olaya nesne yönelimli bakılmasından ve bahsedilenlerin bir nesnenin özelliği veya metodu olmasından kaynaklanmaktadır.

Nesne yönelimli tasarımda, nesneler arası çeşitli ilişki türleri de bulunmaktadır. Daha önceki programlama yaklaşımlarından farklı olarak, nesneler arasında miras ilişkisi, münasebet ve haberleşme gibi ilişkilerden bahsedilebilir.

Nesne Yönelimli Programlama ve C++

Daha önce bahsedildiği üzere, C++ dili, nesne yönelimli bir dil olduğu kadar C dilini de destekleme derdinden dolayı bazı problemler barındırır. Bu bölümde, C++ dilinde basit bir sınıf ve bu sınıftan üretilen nesnenin elemanlarına nasıl erişildiği anlatılacaktır.

C++ dilinde sınıf tanımı için class kelimesi kullanılır. Örneğin şirketimiz için geliştirilen bir programda, çalışanlar birer nesne olacaktır. Bu nesnelerin tanımlanabilmesi için, öncelikle bu nesneleri belirten sınıf (class) tanımının yapılması gerekir. Aşağıda, örnek bir sınıf tanımı verilmiştir.

class Calisan{
   public:
    char isim[20];
    char soyisim[20];
    int maas;
};

Yukarıda tanımlanan sınıf, basitçe bir çalışan sınıfını belirlemektedir ve çalışanın ismi, soyismi ve maaşı bilgilerini tutmaya yarar. Bu sınıftan bir nesne üretmenin iki yolu bulunur:

Calisan ali;

Veya

Calisan *ali = new Calisan();

İlk yöntemde, bir değişken olarak ali tanımlanır ve bu değişken için hafızada (RAM) yer ayrılır. Tek bir çalışan bilgisinin tutulabileceği bu değişkenin özelliklerine (properties) erişilirken . operatörü kullanılır:

ali.maas = 100;
ali.isim = "Ali";
ali.soyisim = "Demir";

şeklinde erişilebilir. İkinci tanımlama yöntemine ise literatürde nesne atıfı (object referrer) veya nesne göstericisi (object pointer) isimleri verilir. Burada kullanılan new kelimesi, aslında hafızada bir çalışan bilgisini tutabilecek kadar yer açılmasını ve aynı zamanda çalışan sınıfında bulunan yapıcının (constructor) çalışmasını sağlar.

Şu anda hiçbir yapıcımız olmadığından bu farkı anlamak için bir yapıcı ekleyerek sınıf tanımımızı aşağıdaki hale getiriyoruz:

class Calisan{
   public:
    char isim[20];
    char soyisim[20];
    int maas;
    Calisan(){
        maas=1000;
        isim = "";
        soyisim="";
    }
};

Örneğimizde, artık Calisan() isimli bir fonksiyon bulunuyor. Bu fonksiyonun özelliği, sınıf ile aynı isme sahip ve geri dönüş tipi (return type) bulunmayan bir fonksiyon oluşudur. Yapıcılar (constructor), bir nesne ilk kez, hafızaya yüklenirken çalışırlar. Dolayısıyla bir çalışan oluşturulduğunda, maaşı otomatik olarak 1000 değerine sahip olacaktır.

Calisan ali = new Calisan();
cout << ali->maas << endl;

Artık bir gösterici olduğu için, nesnenin özelliklerine, yukarıda görüldüğü üzere, -> işlemi ile erişilebilmektedir. Yukarıdaki kod çalıştırılırsa, ekranda 1000 değeri görülecektir.

Son olarak sınıf tanımı içerisinde metot tanımlamasını açıklayalım.

Bir çalışanın zam almak gibi bir fonksiyonu olduğunu düşünelim ve yukarıdaki koda, fonksiyonumuzu ekleyelim:

class Calisan{
   public:
    char isim[20];
    char soyisim[20];
    int maas;
    Calisan(){
        maas=1000;
        isim = "";
        soyisim="";
    }

    void zam(int miktar){
        maas = maas + miktar;
    }
};

Yapılmak istenen zam miktarını, parametre olarak alan ve çalışanın maaşına ekleyen bir metot görüldüğü üzere kodlanabilir.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir