C++ dilinin C ye göre hangi üstünlükleri vardır?

taydin

Timur Aydın
Staff member
Katılım
24 Şubat 2018
Mesajlar
21,727
C++ dilinin, C ye göre sağladığı ilave özellikleri genel olarak listeleyelim:
 
======== Nesnel Programlama (Object Oriented Programming) ========

Bunu da şu alt başlıklar altında inceleyebiliriz:

==== a) Encapsulation: C++ dilinde, veri yapıları ile bu verileri işleyen kodlar, "class" adı verilen bir soyutlama kavramı altında birbiri ile sıkı bir şekilde ilişkilendirilir. Böylece bu veri yapılarını hangi fonksiyon işleyecek? Acaba doğru fonksiyona mı verdik? gibi tereddütler ortadan kalkmış oluyor. Belli bir class'dan nesneler türetiyoruz ve bu nesnelerin hem kendilerine özgü verileri, hem de kendilerine özgü davranış biçimi elde ediyoruz. C dilinde böyle bir yapı yoktur. Veriler ayrıdır, Kodlar ayrıdır. Belli bir veri için doğru kodu kullanmak, programcının sorumluluğundadır.

==== b) Abstraction: C++ dilinin sağladığı "class" kavramı ile türetilen nesneler, yaptıkları işın detaylarını dış dünya'ya gizlerler, ve sadece o nesnenin etkili bir şekilde kullanması için gerekli arabirimi dışa açık hale getirirler. Bu, büyük çaplı, karmaşık programlarda çok büyük bir avantajdır. Detaylarda kaybolmadan, daha üst seviyede düşünüp ona göre tasarım yapmanın önünün açar.

==== c) İnheritance: C++ dilinde, "class" ile oluşturulan temel nesneler, daha karmaşık ve daha fazla işlevsellik sağlayan "üst nesnelerin" yapıtaşı olarak kullanılabilir. Örneğin bir grafik kütüphanesinin sağladığı alt seviye nesneleri düşünelim.

Kod:
class POINT
{
private:
   int x;
   int y;
};

class PIXEL: public POINT
{
private:
   unsigned int color;
};

Şimdi burada ne yaptık? Temel yapıtaşı olarak POINT var elimizde ve iki boyutlu koordinat sistemindeki bir noktayı ifade ediyor. Bu yapıtaşını geliştirip PIXEL yapıtaşını oluşturuyoruz. PIXEL, POINT'un sağladığı bütün imkanları içeriyor, ama onlara renk değerini tanımlama olanağını ekliyor. Bu sistem, değişik amaçlar için aynı kodu tekrar tekrar yazıp gereksiz fazlalığın önüne geçmesi açışından çok büyük bir avantajdır.

==== d) Polymorphism: C++ dilinin en güçlü ve kullanışlı özelliklerinden birisi de polymorphism olayıdır. Burada, aynı temel yapıtaşından türetilmiş, ama ilave olarak farklı davranışlar gösteren nesneler tanımlanabilir. Aşağıdaki programı inceleyelim:

Kod:
#include <stdio.h>

class COMP_FILE
{
public:
   virtual void uncompress() = 0;
};

class ZIP_FILE : public COMP_FILE
{
public:
   void uncompress()
   {
      printf("uncompressing ZIP_FILE\n");
   }
};

class RAR_FILE : public COMP_FILE
{
public:
   void uncompress()
   {
      printf("uncompressing RAR_FILE\n");
   }
};

class LZO_FILE : public COMP_FILE
{
public:
   void uncompress()
   {
      printf("uncompressing LZO_FILE\n");
   }
};

void uncompress_file(COMP_FILE& file)
{
   file.uncompress();
}

int main()
{
   ZIP_FILE zip;
   RAR_FILE rar;
   LZO_FILE lzo;

   uncompress_file(zip);
   uncompress_file(rar);
   uncompress_file(lzo);
}

[ta@bonsai ~]$ ./uncompress
uncompressing ZIP_FILE
uncompressing RAR_FILE
uncompressing LZO_FILE
[ta@bonsai ~]$

Burada COMP_FILE diye, genel anlamda sıkıştırılmış bir dosyayı temsil eden class var. Bundan türetilmiş olan ZIP_FILE, RAR_FILE, LZO_FILE class'ları var. Eğer bu üç class'ı program içinde sadece COMP_FILE pointer olarak kullanırsak, kesinlikle tam olarak ZIP dosyası mı, RAR mı, LZO mu bilmemize gerek olmadan bu dosyaları açabiliriz. Bunun için uncompress_file fonksiyonuna COMP_FILE olarak nesneyi aktarıyoruz, o fonksiyon da, nesnenin uncompress alt fonksiyonunu çağırıyor. Ve nesnenin ne olduğuna bağlı olarak da, doğru bir şekilde dosya açılmış oluyor!

Bu kavram, birçok çeşit nesne ile çalışıyorsak, ve bu nesneler büyük ölçüde aynı davranışı gösteriyor, ama birkaç alanda birbirinden ayrılıyorsa, programımızı çok daha temiz ve basit haline getirecektir.
 
Son düzenleme:
======== Şablonlar veya Jenerik Programlama (Templates or Generic Programming) ========

C++ dilinin büyük avantaj sağlayan başka bir özelliği de jenerik programlamadır. Fonksiyonlar, operatörler, ve class'lar için şablon tanımlamaları yaparak, kullanılan veri tiplerine göre doğru fonksiyon, operatör, ve class yapılarını otomatik olarak oluşturabiliriz. Şu örnek programa bakalım:

Kod:
#include <stdio.h>

template <typename T>
void swap(T& a, T& b)
{
   T temp;

   temp = a;
   a = b;
   b = temp;
}


class COORD
{
public:
   int x;
   int y;
};

int main()
{
   int val1 = 10;
   int val2 = 20;

   swap(val1, val2);

   COORD c1 = {100, 200};
   COORD c2 = {500, 1000};

   swap(c1, c2);
}

Burada "jenerik" bir swap fonksiyonu tanımlıyoruz. Sonra da bu fonksiyonu varsayılan T tipine göre gerçekleştiriyoruz. Sonra da artık bu fonksiyonu BÜTÜN TİPLER için kullanabiliriz!

Buna benzer şekilde aritmetik ve başka operatörler için de şablonlar oluşturup her durumda doğru davranışı göstermesini sağlayabiliriz. Veya bir T tipine göre class tanımlamaları yapabiliriz. Gene büyük çaplı ve karmaşık programlarda hayat kurtarıcı bir özellik.
 
Son düzenleme:
======== İsim Alanları (Namespaces) ========

Büyük çaplı ve karmaşık programlarla uğraşırken, fonksiyon ve değişken sayısı o kadar çok fazlalaşır ki, artık yeni fonksiyon ve değişken isimleri bulmak epey zor hale gelir, çakışmalar meydana gelmeye başlar. İşte bu nokdata C++, her fonksiyon veya değişkeni ayrı ayrı "isim alanlarına" dahil etmemizi sağlar. Böylece isim çakışmalarını önlemiş oluruz. Aşağıdaki örneğe bakalım:

Bir kütüphanenin içerisinde iki tane "send" fonksiyonu tanımlıyoruz, ama her birisini ayrı bir isim alanına koyuyoruz. Birisi email ile mesaj gönderen, diğeri ise SMS ile mesaj gönderen. Aynı şekilde email ve sms ile ilgili başka bir sürü fonksiyon koyuyoruz buraya. Fonksiyonların isimleri hep aynı, sadece isim alanları farklı.

Kod:
namespace email
{
   void prepare()
   {
      // prepare for sending
   }

   void send(const char* message)
   {
      // send the message as an email
   }
}

namespace sms
{
   void prepare()
   {
      // prepare for sending
   }

   void send(const char* message)
   {
      // send the message as an SMS
   }
}


Sonra da email ile ilgili işlerin yapıldığı bir kaynak dosyası olan email.cpp'de şunu yapıyoruz:

Kod:
using namespace email;

void func1()
{
   prepare();
   send("test message");
}


Gene aynı şekilde, sms ile ilgili işlerin yapıldığı bir kaynak dosyası olan smsl.cpp'de şunu yapıyoruz:

Kod:
using namespace sms;

void func2()
{
   prepare();
   send("some test");
}


Şimdi burada şunu düşünebilirsiniz: fonksiyonlara ön takma koyarak da bu işi çözebiliyoruz. Evet, ama büyük çaplı, karmaşık bir programda yapacağınız ön takmalarda devasa uzunlukta fonksiyon isimleri elde edersiniz ve programın anlaşılmasını zorlaştırırsınız. Ama isim alanları kullanırsanız, fonksiyon ismi aynı, çok kısa, ve tam olarak yapılan işi yansıtıyor. Sadece hangi ortam ve şartlarda o işin yapıldığı değişiyor.
 
Son düzenleme:
======== Operatör ve Fonksiyon Overloading ========

Bazan bir fonksiyon yazarız ve bu fonksiyonun verilen argümanların sayısına göre farklı davranış göstermesini isteriz. İşte C++'da function overloading ile bunu yapmamız mümkün.
 
======== Nesne Referansları (Object References) ========

C++'da bir nesneyi temsil eden, ama değiştirilemeyen "reference" diye bir kavram vardır. C'deki pointer gibidir, ama pointer'lar sonrada değiştirilebilir, veya bir bug'dan dolayı içeriği bozulabilir, ve başlarına birçok başka musibet gelebilir. Ama C++ referansları, bir defa değeri atanan, ve sonradan asla değiştirilemeyen pointer'lar gibidir. Güvenli ve doğru çalışan ve kolay anlaşılan program geliştirmek için C++'ın sağladığı en iyi özelliklerden birisidir.
 
======== Exception Handling ========

C'de yazılmış bir programın, çalışma sırasında birçok yerinde olağanın dışında durumlar ortaya çıkabilir. C kütüphanesi fonksiyonları hata döndürebilir, kendi yazdığımız fonksiyonlar hata döndürebilir vesaire. Oluşabilecek bütün bu olağandışı durumları kontrol etmek ve ona göre program akışını değiştirmek C dilinde çok zordur. Bir programın boyutu bu nedenle 5 katına çıkabilir, ve gene de bütün durumları gerçek anlamda kapsadığımızdan emin olamayız.

Aynı şekilde C'de yazılmış bir programda, bir fonksiyon işini yapmak için diyelim hafıza ayırdı, bir dosya açtı, bir soket oluşturdu. Aralarda da farklı işler yapıyor. Eğer bir aşamada bir hata oluştu ise, o fonksiyonun duruma göre ya soketi serbest bırakması lazım, ya dosyayı kapatması lazım, ya ayırdığı hafızayı serbest bırakması lazım, yada bunların belli bir kombinasyonu, veya hepsini yapması lazım. Hatanın hangi aşamada meydana geldiğine göre yapılacak iş değişiyor. Ama C++'da bunu exception handling ve özel wrapper class'larla çok temiz, çok basit bir şekilde halletmek mümkün.

C++ ile, olabilecek bütün hataları tespit eden, bunların gereğini doğru bir şekilde yapan, ve o aşamaya kadar ayrılan kaynakları serbest bırakan kod yazmak çok kolaydır ve hatasız, güvenli program yazmak açısından bulunmaz bir nimettir. Belli bir karmaşıklığa ulaşan programlarda exception handling özelliğini mutlaka kullanmak lazım.
 

Çevrimiçi üyeler

Forum istatistikleri

Konular
5,787
Mesajlar
98,998
Üyeler
2,464
Son üye
s4met

Son kaynaklar

Son profil mesajları

cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Kesici/Spindle hızı hesaplamak için SpreadSheet UDF'leri kullanın, hesap makinesi çok eski kalan bir yöntem :)
Dr. Bülent Başaran,
Elektrik ve Elektronik Mühendisi
Yonga Tasarım Özdevinimcisi
Üç güzel "çocuk" babası
Ortahisar/Ürgüp/Konya/Ankara/Pittsburgh/San Francisco/Atlanta/Alaçatı/Taşucu...

Back
Top