C++ Classes & Data Abstraction


#1
  * {
    font-family: Georgia, Cambria, "Times New Roman", Times, serif;
  }
  html, body {
    margin: 0;
    padding: 0;
  }
  h1 {
    font-size: 50px;
    margin-bottom: 17px;
    color: #333;
  }
  h2 {
    font-size: 24px;
    line-height: 1.6;
    margin: 30px 0 0 0;
    margin-bottom: 18px;
    margin-top: 33px;
    color: #333;
  }
  h3 {
    font-size: 30px;
    margin: 10px 0 20px 0;
    color: #333;
  }
  header {
    width: 640px;
    margin: auto;
  }
  section {
    width: 640px;
    margin: auto;
  }
  section p {
    margin-bottom: 27px;
    font-size: 20px;
    line-height: 1.6;
    color: #333;
  }
  section img {
    max-width: 640px;
  }
  footer {
    padding: 0 20px;
    margin: 50px 0;
    text-align: center;
    font-size: 12px;
  }
  .aspectRatioPlaceholder {
    max-width: auto !important;
    max-height: auto !important;
  }
  .aspectRatioPlaceholder-fill {
    padding-bottom: 0 !important;
  }
  header,
  section[data-field=subtitle] {
    display: none;
  }
  </style></head><body>

C++ Classes & Data Abstraction

C++ dilinin en güçlü olduğu alanlardan bir tanesi data abstraction. Nesne yönelimli programlama data abstraction demek değil. Data abstraction anlamı veri soyutlama. Problem domaininde ki bir veriyi yazılımsal olarak nasıl temsil edeceğim demek. Hikaye şöyle user defined türlerimiz olmasa elimizde sadece primitive türler var, bu türlerle modellenebilecek veriler var. Ama problem domaininde bizi ilgilendirecek verilerin çoğu daha komplex. a + bi gibi bir sayı gibi yada bir üniversitede okuyan bir öğrencinin bilgileri.(tüm bilgileri) En güzel örnek olarak programlama kitaplarında genelde tarih bilgisi veriliyor. Tarih bilgisi tipik olarak gün ay yıl. Dilin bize sunduğu avantajlar olmasaydı şöyle yapıcaktık, 3 tane değişken alacaktık, dilin kuralları gereği bu 3 değişken arasında bir bağlantı kurulmasa da dilin araçlarıyla logic olarak biz bir bağlantı kuracaktık. Bunun da getirdiği bir sürü problem olacaktı. Data abstraction yönünden güçlü olması demek daha komplex türleri primitive türleri kullanıyormuş gibi kolaylıkla kullanabilmektir. İşte bu konuda C++ dilinde class(sınıf)lar var.

Şimdi bahsedeceğim C++ dilinin sınıf kavramı, nesne yönelimli programlamanın sınıfı değil.

~> Sınıf konusu C++ dilinde user defined bir tür.

~> class bir keyword.

~> Bu türü doğrudan Data ismi ile kullanılabilir

class keyword

~> Blok içinde sınıfın öğelerini tanıtacağız


Sınıf Öğeleri

~> Veri öğeleri (Data member)
~> Fonksiyonlar öğeleri (Member function)
~> Tür öğeleri (Nested type)

~> C de birlikler ve yapılar artık c++ da sınıf oldu

~> Sınıf üye fonksiyonları semantik bir maske, gizleme

~> class değilde struct ile bir sınıf oluşturulsaydı default erişim bölümü public olucaktı, public class yerine struct kullanılır

~> class bir scope fakat public, private, protected birer scope değil

~> C++ da sınıf dışı gördüğümüz fonksiyonlara global fonksiyon diyeceğiz, sınıf içi tanımlanan fonksiyonlara member function

~> Structlardan farklı olarak, sınıfların erişim ayrıcalığı var

~> Sınıfın public, protected ve private bölümleri var

Erişim Belirleyiciler

~> private sınıfın kendi kodlarına açık fakat sınıfın müşterilerine kapalı, compile timeda kontrol edecek,

~> protected, kalıtımla birlikte önem kazanacak(inheritance), sınıfın clientlarına kapalı, inherit edilince açık

Class Scope - Duplicate member x

.(nokta) operatörü
->(ok) operatörü
:: (çözünürlük operatörü)


~> Aynen yapılarda olduğu gibi bir sınıf nesnesi yoluyla sınıfın öğesine nokta yoluyla ulaşabiliyoruz, önemli olan burada öğe aramanın nasıl yapıldığı

~> derleyici . operatörünün önce sol operandına bakar, bir sınıf türünden olduğunu anlarsa sağ operandını class scope ta arar

~> bir sınıf türünden pointer ise ptr->x ok operandının solu sınıfmı, sağ operandını o class içinde arar

myclass.*ptr;
ptr->x;

Name Lookup

~> Derleyici aradığı ismi bulunamassa her zaman error, bulursa geçerli diye birşey yok… Aramada 3 durum var
1. nokta operatörü
2. -> operatörü (o sınıf türünden adres olucak)
3. :: operatörü (sınıf türünden olucak)
~> operatörlerinin sağ operantları class scope ta aranır

Myclass m;
m.x; // isim arama önce yapılıyor, sonra class private olursa x aradım buldum, private alanına erişim hatası

~> private kodlarını gizlemek için PIMPL idiomu kullanılır, bu idiomun hem compile time hemde run time maliyeti var.

~> En katı korunan kısım private, hem clientlara hem de türetilmiş sınıflara kapalı

~> protected clientlara kapalı, türetilmiş sınıflara açık

~> public herkese açık

~> C de şöyle diyebilirdik, client bunları bil ama kullanma, ben senin bu öğelere doğrudan erişmeni istemiyorum gibi.


PİMPL İDIOMU HAKKINDA

~> Madem amaç private bölümü gizlemek, engellemek o zaman neden private sınıf tanımında yazıyoruz ki? Muhtemelen başlık dosyasında olucak, eee madem clientların bilmesini istemiyorum başlık dosyasına koyarsam clientlar bunu görmeyecek mi? Malesef görecekler, böyle bir açık var ama teknik zorunluluktan oluyor. Neden? Çünkü client ın bunu kullanması yanında cpp dosyasıda bunu kullanıyor. Özel önlem alınabilir ama default durum client bunu görebiliyor, bunları göstermemenin yolu var buna pimpl idiomu deniyor. (Pointer Implemantatıon)

~> Compile time maliyeti var, runtime maliyeti var (pimpl idiomu)

~> Veri elemanları private bölümü, member functionlar sınıfın public bölümüne, sınıfın public bölümü genelde bu sınıf için işleri yapıcak fonksiyonlardan oluşacak

~> Pimpl idiomu için ayrıcı bir makale yazıcam. Konuyu dağıtmamak için devam ediyoruz….


Bir önce ki makalede de belirttiğim gibi :: çözünürlük operatörü ile ilgili şöyle ufak bir örnek yapalım.

:: operatoruGlobal alanda x isimli birsey bulunamadi

~> Üye fonksiyon uydurmasının anlamı şu, daha önce global scope ta bulunan fonksiyonlar artık class scope içine dahil oluyorlar, amaç clienta daha iyi bir interface vermek, mydate.set() mydate in set fonksiyonu gibi.

Artık üye fonksiyonlar geldi, global fonksiyonlar hiç kullanılmayacak mı? ~>Hayır alakası yok, C de zaten başka yolumuz yok ama C++ da sınıfla ilgili iş yapan fonksiyonların artık çoğu class içinde olucak ama global fonksiyonlarda olabilir

Function Member

~> Uygulama pratiğinde her sınıf için bir header dosyası oluşturulur

~> Header dosyası oluştururken ilk yapacağımız multiple inclusion, amaç bir başlık dosyasını birden fazla import edilmesini engellemek.

https://en.wikipedia.org/wiki/Include_guard

Multiple Inclusion || Include GuardScope Adres Bilgisi

~> Sınıfta public veya private önce olacağı durumlar olucak, belli senaryolar durumda bunda özgürüz.

~> Global bir fonksiyon ile sınıfın üye fonksiyonu asla overload değildir.

~> Sınıfın üye fonksiyonu default u nonstatic

~> Eğer sınıf içinde bir fonksiyonda static keywordu varsa bunu C deki ile karıştırmayacağız. Bu sınıf nesnesinin adresine ihtiyaç duymayan demek

~> non static, nesneye ihtiyacı var(static keywordu almayanlar)


Sınıfın Üye Fonksiyonları Arasında İsim Arama (name lookup)

~> C dilinde block scope, global scope alanı vardı, şimdi class scope eklendi.(C++ için)

~> Block scope un class scopa önceliği var.

~> isim arama yapılır, eğer aranan isim bulunursa arama durur (javada böyle değil), yani isim 1 kez aranır, bulunan isimden sonra asla isim arama yapılmaz.

Scope && Erişim Konusu

Const Öğeler

~> Const öğelerin amacı nesneyi değiştirmek değil, bu bir get fonksiyonu, yani bu nesnenin varlık nedeni nesneyi değiştirmek değil

~> Const olmayan bir üye fonksiyon const üye fonksiyonu çağırabilir ama const üye fonksiyon const olmayan bir üye fonk çağıramaz.

~> Const overloading (yine function overloading tabi ama const)

~> Native erişim biçimi, this göstericisi ile ve çözünürlük operatörü ile

~> C++ dilinde this->x olarak kullanmayın… (java, c# taki gibi değil), normal koşullarda bunu kullanma

~> Sınıfın veri elemanlarına this gösterici ile erişilebiliriz


This Pointerı

~> Bu fonksiyon hangi nesne için çağırıldı ise o nesnenin adresi

~> *this demek o adresteki nesne

~> this kendisi const olan bir gösterici

this

~> Nesnenin kendisi ise nokta operatörü

~> Pointer ise ok(->) operatörü kullan

Genel Bir Ornek

Ufak bir tekrar

~> Sınıflarda .(nokta) operatörü
~> Pointerlarda ->(ok) operatörü
~> :: çözünürlük operatörü(erisim) Myclass::x
~> Sadece ::x dersek global değişken
~> :: 2 kullanımı var… SINIFLARDA ve NAMESPACE alanlarında

~> cons olan fonksiyon, cons olmayan üye fonksiyonu çağıramaz
~> cons olmayan bir fonksiyon, cons olan fonk çağırabilir


Üyeleri 3 ayrı erişim var

~> Native doğrudan erişim x = 45; y = 26; gibi
~> this ile erişim
~> çözünürlük operatörü(::) ile erişim


Dereference edersek;

~> * this, Myclass m; m.func();

~> *this m’nin kendisi yani hangi nesne için çağırılırsa o nesnenin kendisi

~> this kendisi const olan bir göstericidir. Data *const this;

~> this atama yapamayız ama *this e atama yapabiliriz

this -> x++; ile (*this).x++; aynıdır

Kaynak: https://goo.gl/UEAfkP