Yeni Başlayanlar İçin C++ Dersleri

Başlatan -DıLgEş-, 20 Kasım 2014 - 15:03:25

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

-DıLgEş-

#25
-Karakter Dizileri
   Diğer dizilerden ayrı olarak bir de C++ dilinde karakter dizileri bulunmaktadır. Bu karakter dizileri şöyle tanımlanır;

<veri tipi> <dizi ismi> [İndex];

   Buradaki index değeri diğer dizi türleri gibi değildir. Burada tanımladığımız karakter dizisinin tutacağı harf sayısını belirtir. Ancak, bu konuda dikkat edilmesi gereken bir husus vardır.
   Her karakter dizisinin sonunda "\0" karakteri bulunur. Bu nedenden olayı belirttiğimiz harf sayısını +1 fazla olarak girmemiz gerekecektir. Örneğin; "Adana" kelimesini bir karakter dizisine yazmak için 6 karakter kullanmak gerecektir:

char kd1[6]="Adana";

   Bu kelime dizi içinde şu şekilde gösterilir:

char kd1[6]={'A', 'd', 'a', 'n', 'a', '\0'};
veya
char kd1[6]={'A', 'd', 'a', 'n', 'a'};

   Karakter dizisinde 6 yerine 8 sayısını da yazabiliriz. Bu konuda sıkıntı olmaz.

Örnek:

#include <iostream>

using namespace std;

int main()
{
char ad[30];

cout<<"Adınızı giriniz: ";
cin>>ad;

cout<<ad;

return 0;
}


   Sakın, klavyeden ismi almak için ad[30] diye bir ifade kullanmayın. Aksi takdirde programdan beklediğiniz sonucu almazsınız.

-Karakter Dizileri Fonksiyonları
   C++ dilinde, karakter dizileri üzerinde işlem yapabilmemizi sağlayan bir kütüphane bulunur. Bu kütüphanenin adı <cstring> kütüphanesidir. Bu kütüphane içinde göreceğimiz fonksiyonlar;

1-> strcpy(dizi1, dizi2) Fonksiyonu
   Bu fonksiyonun veri tipi void'tir. Değer döndüremez. Fonksiyonun görevi s2 dizini s1 içine kopyalamaktır.

strcpy(dizi, "İstanbul");

   Burada, dizi olarak tanımlanan karakter dizimiz "İstanbul" olarak değiştirildi. Aşağıdaki programda bunu daha iyi anlayacağız.

Örnek:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char krd1[]="İstanbul";
    char krd2[]="Ankara";

    cout<<"Dizi1: "<<krd1<<endl;
    cout<<"Dizi2: "<<krd2<<endl;

    strcpy(krd1, krd2);

    cout<<"Dizi1: "<<krd1<<endl;
    cout<<"Dizi2: "<<krd2<<endl;

    return 0;
}


   Gördüğünüz gibi, dizi1 değerinde tuttuğumuz "İstanbul" değeri strcpy fonksiyonu yardımıyla, "Ankara" olarak değiştirildi.

2-> strcat(dizi1, dizi2) Fonksiyonu
   Bu fonksiyon dizi1 dizisine, dizi2'ye ait değer eklenir. Örneğin;

dizi[]="İst"
strcat(dizi, "anbul");

   Bu fonksiyon sonrası, dizi adlı karakter dizimiz, "İstanbul" olarak değiştirilecektir.

Örnek:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char lin1[]="Linux";
    char lin2[]="-Ubuntu";

    cout<<"Dizi1: "<<lin1<<endl;
    cout<<"Dizi2: "<<lin2<<endl;

    strcat(lin1, lin2);

    cout<<"Dizi1: "<<lin1<<endl;
    cout<<"Dizi2: "<<lin2<<endl;

    return 0;
}


   Bu kodda lin1 dizisi strcat fonksiyonunun kullanımından sonra "Linux-Ubuntu" olarak değiştirilecektir.

3-> strlen(dizi) Fonksiyonu
   Fonksiyona gönderilen karakter dizisinin uzunluğunu verir. Dönüş değerinin bir tamsayı olarak gönderir.

Örnek:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char dizi[]="Ubuntu Türkiye Forum";

    cout<<strlen(dizi);

    return 0;
}


   Elimizdeki dizi adlı karakter dizimizin boyutu, sondaki '\0' karakteri ile bir karakter daha kazanıp dönüş değerini 21 olarak gönderdi.

4-> strcmp(dizi1, dizi2) Fonksiyonu
   Bu fonksiyonu dizi1 değeri ile dizi2 değerini karşılaştırır. Bu karşılaştırma şu şekilde olur:

Alıntı Yap
Büyük harfler ASCII tabloda daha önce bulunur. Bu durumda küçük harfle başlayan bir string ile büyük harfle başlayan bir string karşılaştırılınca, büyük harfle başlayan sözlükte daha önce yer alıyormuş gibi cevap alırız.

Alıntıdır...

   Bu fonksiyonda döndürülen değerler;

-1 -> dizi1<dizi2
0  -> dizi1==dizi2
1  -> dizi1>dizi2

Örnek:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char dizi1[]="Ubuntu Türkiye Forum";
    char dizi2[]="ubuntu türkiye forum";

    cout<<strcmp(dizi1, dizi2);

    return 0;
}


   Örneğimizde dizi1, dizi2'den küçük olduğundan biza döndürülen değer -1 olacaktır. Eğer, her iki dizi aynı değere sahip ise, fonksiyon bize 0 değerini gönderecektir.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..

-DıLgEş-

#26
-Pointer Nedir?
   Pointer, C++ dilinde değişkenin adresini taşıyan bir türdür. İşaretçilerin iki türlü operatörü vardır:

*=Referance Operatörü
&=Dereferance Operatörü

   Şimdi sırasıyla bu operatörleri görelim:

1-> &(dereferance) Operatörü
   Bu operatör, önüne koyulduğu değişkenin bellekte tutulan adresini döndürür.

Örnek:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int s=16;

    cout<<"Değişken değeri: "<<s<<endl;
    cout<<"Değişken adresi: "<<&s<<endl;

    return 0;
}


Çıktı:

Değişken değeri: 16
Değişken adresi: 0xbfd846f8


   Değişken adresi her bilgisayarda aynı olmaz. Bu sebepden dolayı yukarıda yazdığımız kodun her bilgisayarda farklı bir çıktı vereceğini bilmemiz gerekecektir.

2-> *(referance) Operatörü
2-> *(referance) Operatörü
   Bu operatör, C++ dilinde başka bir deyişle pointer olarak geçer. Pointerler ile ilgili klasik bir tanım vardır:

Alıntı Yap
Pointer, bir işaretçidir ve adres tutar. Başına "*" işareti konmuş her bir ifade pointerdir.

-Pointer Değişkenler
   Hatırlarsanız tanımlanan bir değişkenin bellekte kendisine bir alan ayırdığını belirtmiştirk. Bu alanlar;

char   = 1 byte
int      = 4 byte
float   = 4 byte
double   = 8 byte

   Pointer olarak tanımlanan bir değişken ise 32 bit sistemlerde 4, 64 bit sistemlerde 8 byte yer kaplar.

Örnek:

int *p;
double *s;
char *ptr;
float *kd;


   Yukarıda tanımlanan değişkenlerin hepsi bir pointerdir ve veri tipi ne olursa olsun, 32 bit sistemlerde 4, 64 bit sistemlerde 8 byte bir alan kaplayacaklardır. Örneğin;

int    *p;

   Bu değişken bir pointerdir demiştik. Peki, bu değişkene nasıl değer aktarılır, adresine nasıl ulaşılır?
   Esasında, bu değişkene veri aktarmak için, "*p" olarak değer aktarabiliriz. Pointerin adresine erişmek için, "p" ismini kullanabiliriz.

Örnek:

#include <iostream>

using namespace std;

int main()
{
    int *p;     //Tamsayı tutan bir pointer tanımladık...
    int a=18;

    p=&a;       //Pointer adresine a değişkenin adresi aktarılıyor.Böylece pointerimize değer ataması yapıyoruz.

    cout<<"Pointer değeri: "<<*p<<endl;
    cout<<"Pointer adresi: "<<p<<endl;      //Adresi belirtmek için * işaretini kaldırıyoruz.
    cout<<"Pointer boyutu: "<<sizeof(*p)<<endl;
    return 0;
}


Çıktı:

Pointer değeri: 18
Pointer adresi: 0xbffd14c4
Pointer boyutu: 4


   Örneğimizde de gördüğümüz gibi bir pointere doğrudan değer ataması yapamayız. Yaptığımız halde program bize "Segmentation fault (core dumped)" hatasını yüzümüze vuracaktır.
   Bu örnekte, şu ana kadar anlatmadığım bir fonksiyon gördünüz. Fonksiyon adı sizeof diye geçmektedir. Bu fonksiyona parametre olarak gönderilen bir değişkenin boyutunu ekrana basar.

Örnek:

#include <iostream>

using namespace std;

int main()
{
    int d1;
    double d2;
    float d3;
    char d4;
    int *d5;
    double *d6;
    float *d7;
    char *d8;

    cout<<"int d1: "<<sizeof(d1)<<"byte"<<endl;
    cout<<"double d2: "<<sizeof(d2)<<"byte"<<endl;
    cout<<"float d3: "<<sizeof(d3)<<"byte"<<endl;
    cout<<"char d4: "<<sizeof(d4)<<"byte"<<endl;
    cout<<"int *d5: "<<sizeof(d5)<<"byte"<<endl;
    cout<<"double *d6: "<<sizeof(d6)<<"byte"<<endl;
    cout<<"float *d7: "<<sizeof(d7)<<"byte"<<endl;
    cout<<"char *d8: "<<sizeof(d8)<<"byte"<<endl;

    return 0;
}


Çıktı:

int d1: 4byte
double d2: 8byte
float d3: 4byte
char d4: 1byte
int *d5: 4byte
double *d6: 4byte
float *d7: 4byte
char *d8: 4byte


   Pointer değişkenlerin çalışma mantığı bu kadar. Anlamadığınız kısımlar için ileti atabilirsiniz...

-Pointer ve Diziler
   C/C++ dillerinde pointer ile diziler arasında bir ilişki bulunmaktadır. Bu ilişkide, bir pointer aynı anda dizinin tüm elemanlarını tutabilir. Örneğin, i adında 4 eleman tutan bir dizimiz olsun;

int i[3]={0,1,2,3};

   Bir de p adında bu diziyi tutacak pointeri tanımlayalım.

int *p;

   Şimdi dizimizin tüm elemanlarını bu pointere aktaralım.

p=i;

   Burada pointerimize tüm dizi elemanlarını aktardık. Şimdi dizi üzerinde yapılan her işlem, pointer üzerinde de yapılmış olacak. Yani, pointerimiz oluşturduğumuz diziyi taklit edecek...

i[0]
i[1]
i[2]
i[3]

   Sadece dizinin değil, pointerimizin de tüm elemanları değişti...

cout<<*p<<endl;      //Ekrana 4 yazdırır.
cout<<*(p+1)<<endl;      //Ekrana 5 yazdırır.
cout<<*(p+2)<<endl;      //Ekrana 6 yazdırır.
cout<<*(p+3)<<endl;      //Ekrana 7 yazdırır.

   Burada, pointer elemanlarına şu şekilde eriştik;

*(<pointer adı> + index);

   İlk elemanda +0 yazmamıza hiç gerek yoktur. Çünkü, index numarası verilmeyen pointerimiz dizinin ilk elemanını ekrana basar.
   Pointerin elemanlarını şu şekilde değiştirebiliriz;

*(<pointer adı> + index)=<yeni değer>;

   Sakın, int pointerine, noktalı bir sayı aktarmayın. Derleyici böyle bir durumda hata verecektir.

-Pointer Dizi Oluşturma
   Const ifadesi kullanılmadan her bir dizinin elemanlarını değiştirebiliyoruz. Peki, madem pointer bir dizi olarak kullanılabiliyor. Neden kendi elemanlarına doğrudan erişemiyoruz?
   İşte bunun için C++ dilinin bellek ayırma ve silme operatörlerinden new ve delete operatörlerini kullanacağız.

1-> New Operatörü
   Bu operatör, pointer olarak oluşturulacak diziye eleman sayısını aktarmada kullanılır. Örneğin *n adında bir pointeri bir dizi yapmak istersek;

<pointer ismi>=new <veri tipi>[index];

   Bu ifadeyi şimdi bir örnekte kullanalım.

Örnek:

#include <iostream>

using namespace std;

int main()
{
    int *n;     //n adında bir pointer tanımladık...
    n=new int[5];   //Pointeri artık bir dizi olarak kullanabiliriz...

    n[0]=10;
    n[1]=20;
    n[2]=30;
    n[3]=40;
    n[4]=50;
    n[5]=60;

    for(int i=0; i<6; i++)
    {
        cout<<i<<". pointer dizi değeri: "<<n[i]<<endl;
    }

    return 0;
}


Çıktı:

0. pointer dizi değeri: 10
1. pointer dizi değeri: 20
2. pointer dizi değeri: 30
3. pointer dizi değeri: 40
4. pointer dizi değeri: 50
5. pointer dizi değeri: 60


   Ben kodu fazla uzatmamak için, for döngüsü kullanarak, tüm dizi elemanlarını döngü yardımıyla ekrana bastırdım. İsterseniz siz, alt alta yazdırabilirsiniz.
   Örnekte, diziyi tanımladık ancak silmedik. İşte bu silme olayını da aşağıdaki operatör yapmaktadır.

2-> Delete Operatörü
   Delete operatörü, new ile oluşturulan bir şeyi silmek için kullanılır. Bu durumda, new operatörünün, bellekte ayırmış olduğu alan boşalacaktır.
   Şimdi aynı örneği tekrar yazalım ancak, bu sefer, delete komutunu kullanalım.

Örnek:

#include <iostream>

using namespace std;

int main()
{
    int *n;     //n adında bir pointer tanımladık...
    n=new int[5];   //Pointeri artık bir dizi olarak kullanabiliriz...

    n[0]=10;
    n[1]=20;
    n[2]=30;
    n[3]=40;
    n[4]=50;
    n[5]=60;

    for(int i=0; i<6; i++)
    {
        cout<<i<<". pointer dizi değeri: "<<n[i]<<endl;
    }

delete [] n; //n dizisi silindi...

    return 0;
}


   Burada en sonda delete operatörüyle new ile ayrılmış boyutu sildik ve bellekte kullandığımız alan tekrar verilmiş oldu.
   Örnekte, delete komutunu şu şekilde kullansaydık;

delete n;

   Tüm dizi elemanları değilde sadece ilk dizi elemanı silinirdi.
   Son olarak fonksiyonlarla ilgili bir pointer konusu kaldı onu bir sonraki konuda göreceğiz.

SORULAR
1. Pointer çalışma mantığıyla ilgili kendinize örnekler yapmaya çalışın. Çünkü pointer ve ondan sonraki gelecek konular C++ dilinin, en zor olduğu konulardır.



Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 29 Temmuz 2015 - 17:19:37

-Bool Tipi
   Bool tipi, bildiğimiz gibi 2 adet değer tutmaktadır. Bunlardan ilki yanlış anlamına gelen 0, ikincisi ise doğru anlamına gelen 1 değeridir.

-Örnek:

#include <iostream>

using namespace std;

int main()
{
    bool a;
    bool b;

    a=10<5;
    b=10>5;

    cout<<"10<5 -> "<<a<<endl;
    cout<<"10>5 -> "<<b<<endl;

    return 0;
}


-Çıktı:

10<5 -> 0
10>5 -> 1


   Örneğimizde iki adet bool tipinde değişken tanımladık. Bunların her birine bir ifade gönderdik ve doğruluklarını test ettik.
   Birinci ifadede 10 sayısı 5'ten küçük olmadığı için 0 yani yanlış değeri döndürecektir. İkinci ifadede 10 sayısı 5'ten büyük olduğu için 1 yani doğru değerini döndürecektir.

-Volatile Komutu
   Volatile komutu const sözcüğü gibidir. Hatırlarsanız sabitleri const anahtar sözcüğüyle tanımlıyorduk. Volatile komutu ise geçici anlamına gelmektedir.
   Bu komut ile yapılan değişken derleme anında değil yürütme anında kontrol edilir.

-Örnek:

#include <iostream>

using namespace std;

int main()
{
    volatile int sayac;

    for(sayac=0; sayac<10; sayac++)
    {
        cout<<"Merhaba Dünya..."<<endl;
    }

    return 0;
}


   Volatile komutu donanım ile birleştirilen C++ programlarında kullanılmaktadır. Ben öylesine sadece volatile komutunu görmeniz için bait bir programda örnek olarak gösterdim.

-Enum Tipi
   Bazı durumlarda sıralı isimlerden oluşan, bir küme tanımlaması istenebilir. Bu tür durumlarda enum tipi kullanılır. Tanımlama şekli;

enum <degiskenadi> {eleman1, eleman2, ... , eleman n};

-Örnek:

#include <iostream>

using namespace std;

int main()
{
    enum mevsim{ilkbahar, yaz, sonbahar, kis};

    enum mevsim a=yaz;

    cout<<"a= "<<a<<endl;

    return 0;
}


   Örneğimiz mevsim içinde tanımlanmış olan yaz değerinin bulunduğu index numarasının çıktısı verilecektir.
   Enum tipinin bir diziden farkı yoktur. İlk eleman 0 değerinden başlar.

enum mevsim {ilkbahar, yaz=5,sonbahar ,kis};

   Böyle bir enum tipini örneğimizde tanımlasaydık, örneğimiz bize 5 değerini verecekti.

-Asm Fonksiyonu
   C++ dilinde yazdığımız program içine assembly kodu ekleyebiliriz. Bu durumda asm fonksiyonu kullanılır.

asm(asm deyimi);

   Program içinde her komut için bir assembly deyimi kullanılmalıdır. Bir asm fonksiyonu içine bir program yerleştirilemez.


Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 30 Temmuz 2015 - 17:12:04

-Sınıflar
   Sınıflar, C ile C++ dilini ayıran en önemli özelliklerinden biridir. Her sınıf, kendine has fonksiyonlar, değişkenler, vs. tutabilir. Sınıflar aşağıdaki gibi tanımlanır:

class <sinifismi>
{
   public:
      ...
      ...
   private:
      ...
      ...
   protected:
      ...
      ...
}nesneler;

   Bir sınıfın içinde tanımlanan herşeye o sınıfa ait oluşturulan nesne ile erişilir. Bir sınıfa ait nesne iki şekilde tanımlanır. Birincisi, yukarıda sınıf sonuna getirilen ";" işaretinden önce sınıfa ait nesne veya nesneler tanımlanır. İkincisi ise sınıf dışında şu şekilde tanımlanır:

<sınıf adı> <nesne adı>;

   Bu şekilde tanımlanan nesneler yerellik ve global olma durumu taşırlar.
   Yukarıdaki bir sınıf tanımlama çeşidinde public, private ve protected anahtar sözcükleri bulunmaktadır. Bu anahtar sözcüklerin tümünü bir sınıf içinde kullanmak zorunda değilizdir. Biz şimdilik public anahtar sözcüğüü kullanalım. Daha sonra açıklayacağım.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    public:
        int Kareal(int x)
        {
            return x*x;
        }

}kareal;

int main()
{
    int sayi;

    cout<<"Karesi alınacak sayıyı giriniz: ";
    cin>>sayi;

    cout<<"Girdiğiniz sayının karesi: "<<kareal.Kareal(sayi)<<endl;

    return 0;
}


   Yukarıda bir sınıf tanımladık ve sınıf içine Kareal adlı bir fonksiyon yerleştirdik ve nesnemiz ile bu fonksiyonu çağırdık.
   Dikkat ederseniz, sınıf elemanlarına "." işareti ile eriştik. Bunun nedeni tanımladığımız nesnenin pointer olarak tanımlanmamasıdır.
   Pointer olarak tanımlanan bir nesne ile sınıf elemanlarına "->" işareti ile erişilir.

Örnek:

#include <iostream>

using namespace std;

class KupAl
{
    public:
        int Kupal(int x)
        {
            return x*x*x;
        }

}*ptr_kupal;

int main()
{
    int sayi;

    cout<<"Küpü alınacak sayıyı giriniz: ";
    cin>>sayi;

    cout<<"Girdiğiniz sayının küpü: "<<ptr_kupal->Kupal(sayi)<<endl;

    return 0;
}


   Bir sınıfa ait birden çok nesne tanımlanabilir. Bu durumda her bir nesne farklı amaçlarla kullanılabilir.

Örnek:

#include <iostream>

using namespace std;

class KareKup
{
    public:
        int Kareal(int x)
        {
            return x*x;
        }

        int Kupal(int x)
        {
            return x*x*x;
        }
}nesne1, nesne2;

int main()
{
    int sayi1, sayi2;

    cout<<"Karesi alınacak sayıyı giriniz: ";
    cin>>sayi1;
    cout<<"Küpü alınacak sayıyı giriniz: ";
    cin>>sayi2;

    cout<<sayi1<<" karesi: "<<nesne1.Kareal(sayi1)<<endl;
    cout<<sayi2<<" küpü:   " <<nesne2.Kupal(sayi2)<<endl;

    return 0;
}


   Bu örnekte, iki nesne tanımladık. Bu nesnelerden ilki Kareal fonksiyonuna, ikincisi ise Kupal fonksiyonuna değer göndermek için kullanılmıştır.
   Bir nesneyi pointer olarak tanımladığımız gibi dizi olarak ta tanımlayabiliriz. Aynı örneği bir de dizi yöntemiyle tekrar yazdıralım.

Örnek:

#include <iostream>

using namespace std;

class KareKup
{
    public:
        int Kareal(int x)
        {
            return x*x;
        }

        int KupAl(int x)
        {
            return x*x*x;
        }
}nesne[1];  //İki elemanlı nesne...

int main()
{
    int sayi1, sayi2;

    cout<<"Karesi alınacak sayıyı giriniz: ";
    cin>>sayi1;
    cout<<"Küpü alınacak sayıyı giriniz: ";
    cin>>sayi2;

    cout<<sayi1<<" karesi: "<<nesne[0].Kareal(sayi1)<<endl;
    cout<<sayi2<<" küpü:   " <<nesne[1].KupAl(sayi2)<<endl;

    return 0;
}


   Şu ana kadar nesnenin her türlü hale gelebileceğini öğrendik. Şimdi başta anlatmadığım o public, private ve protected komutlarına...

-Public, Private ve Protected
   Sınıflar daha pek çok işe yararlar. Şu ana kadar pek bir şeyi sınıflar ile yapmadık. Bu başlık altında sınıflara ait 3 anahtar sözcüğünü göreceğiz. Hemen başlayalım.

1-> Public Komutu
   Şu ana kadar örneklerimizde hep bu sözcüğü kullandık. Bu sözcük, derleyiciye benden sonra tanımlanan herşey bir nesne ile erişebilir anlamını taşır.
   Eğer, biz bu sözcüğü kullanmasaydık sınıf içine yerleştirdiğimiz hiçbir elemana nesne ile erişemezdik. Bir başka erişim yolunu ilerki konulara bırakıyorum.

2-> Private Komutu
   Public veya protected sözcüğünü yazmadığımız durumlarda private sözcüğü devreye girmektedir. Bu sözcük ile nesnenin sınıf elemanlarına erişmesi mümkün değildir.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    private:
        int Kareal(int x)
        {
            return x*x;
        }
}nesne;  //İki elemanlı nesne...

int main()
{
    int sayi1;

    cout<<"Karesi alınacak sayıyı giriniz: ";
    cin>>sayi1;

    cout<<sayi1<<" karesi: "<<nesne.Kareal(sayi1)<<endl;

    return 0;
}


   Bu örneği derlemeye kalktığınızda aşağıdaki gibi bir derleyici hatası alacaksınız:


main.cpp: In function 'int main()':
main.cpp:8:13: error: 'int KareAl::Kareal(int)' is private
         int Kareal(int x)
             ^
main.cpp:21:49: error: within this context
     cout<<sayi1<<" karesi: "<<nesne.Kareal(sayi1)<<endl;
                                                 ^


   Bu hatanın anlamı kısaca, "Belirtilen fonksiyona erişim izni yoktur." demektir.
   Bu tür durumlarda bu fonksiyona sadece sınıf içinde erişim vardır.

3-> Protected Komutu
   Bu sözcükten sonra tanımlanan herşey o sınıftan türeyen başka bir sınıf ile erişim izni açıktır. Bu olayı daha sonra göreceğiz.

-Yapıcılar ve Yokediciler
   Sınıflar oluşturulurken, nesne yaratıldığında bir takım işler gerçekleştirilmesi istenebilir. Bu tür durumlarda C++ dilinin bize sunmuş olduğu yapıcı(constructor) fonksiyonlarını kullanacağız.
   C++ dilinde program sona erdiğinde nesnenin otomatik olarak yok olması için de yokedici(destructor) fonksiyon kullanılır. Şimdi onları sırayla görelim...

1-> Yapıcı Fonksiyonlar
   Yapıcılar, oluşturulan bir nesne için ilk değer veya başlangıcında yapılacak bir takım işler için kullanılır. Yapıcılar şu şekilde tanımlanır:

<sınıf adı>()
{

   ...
   ...
   ...
}

   Yapıcı tanımlanırken hiçbir dönüş değeri alamaz. Aşağıdaki örnekte yapıcıları daha iyi anlayacağız.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    public:
        KareAl()
        {
            cout<<"Nesne Yaratıldı..."<<endl;
        }
}nesne;  //İki elemanlı nesne...

int main()
{
    return 0;
}


Çıktı:

Nesne Yaratıldı...


   Gördüğünüz gibi nesne yaratıldığı zaman otomatik olarak yapıcı çağrılır. Bir yapıcı o sınıf için yaratılan tüm nesneler için kullanılır.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    public:
        KareAl()
        {
            cout<<"Nesne Yaratıldı..."<<endl;
        }
};  //İki elemanlı nesne...

int main()
{
    cout<<"Nesne henüz yaratılmadı..."<<endl;

    KareAl object;

    cout<<"Yapıcı çağrıldı..."<<endl;

    KareAl nesne;

    cout<<"İkinci nesne için yapıcı çağrıldı..."<<endl;

    return 0;
}


Çıktı:

Nesne henüz yaratılmadı...
Nesne Yaratıldı...
Yapıcı çağrıldı...
Nesne Yaratıldı...
İkinci nesne için yapıcı çağrıldı...


   Bu örnekte yapıcı olayını anlamışızdır herhalde. Yine anlamadığınız yerler olabilir. Bu durumda konu altında ileti yazarak cevaplayabilirsiniz.

1-> Yokedici Fonksiyonlar
   Nesne silindiğinde yapılacak işlemleri belirtmek için yokedici(destructor) fonksiyon kullanılır. Yokediciler aşağıdaki şekilde tanımlanır:

~<sınıf adı>()
{

   ...
   ...
   ...
}

   Eğer programcı bir yokedici tanımlamazsa, derleyici otomatik olarak içi boş bir yokedici tanımlar. Şimdi yukarıda yaptığımız örneklere bir de yokedici ekleyerek çalıştıralım.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    public:
        KareAl()
        {
            cout<<"Nesne Yaratıldı..."<<endl;
        }

        ~KareAl()
        {
            cout<<"Nesne Yokedildi..."<<endl;
        }
}nesne;  //İki elemanlı nesne...

int main()
{
    return 0;
}
[code]

[color=brown]Çıktı:[/color]
[code]
Nesne Yaratıldı...
Nesne Yokedildi...


   Bir yokedici, tıpkı yapıcı gibi o sınıf tarafından üretilen tüm nesneler için geçerlidir.

Örnek:

#include <iostream>

using namespace std;

class KareAl
{
    public:
        KareAl()
        {
            cout<<"Nesne Yaratıldı..."<<endl;
        }
        ~KareAl()
        {
            cout<<"Nesne Yokedildi..."<<endl;
        }
};  //İki elemanlı nesne...

int main()
{
    cout<<"Nesne henüz yaratılmadı..."<<endl;

    KareAl object;

    cout<<"Yapıcı çağrıldı..."<<endl;

    KareAl nesne;

    cout<<"İkinci nesne için yapıcı çağrıldı..."<<endl;
    cout<<"Nesneler yokediliyor..."<<endl;

    return 0;
}


Çıktı:

Nesne henüz yaratılmadı...
Nesne Yaratıldı...
Yapıcı çağrıldı...
Nesne Yaratıldı...
İkinci nesne için yapıcı çağrıldı...
Nesneler yokediliyor...
Nesne Yokedildi...
Nesne Yokedildi...


   Yapıcılar ve yokedici fonksiyonları şimdilik burada noktalayalım. Yapıcıların kalan kısımlarını ilerki konulara bırakalım.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..

-DıLgEş-

-Kalıtım Nedir?
   Kalıtım(inheritance), bir sınıfın başka bir sınıftan türetilmesidir. Bir nevi, sınıflar arasındaki ilişkileri düzenler. Örneğin elimizdeki iki sınıf olsun. Bunlar A ve B sınıfıdır. Biz B sınıfını A sınıfına benzetmek için kalıtım yani türetmeyi kullanırız.
   Kalıtım olayı iki türlü olur. Bunlar;

-> Genel Kalıtım(Public Inheritance)
   Temel sınıftan yeni sınıflar türetmek için kullanılır. Genel kalıtım, bunlar arasındaki ilişkiyi düzenlemek için kullanılır. Böylece, temel sınıfın nesnesi belli koşullarda alt sınıfın nesnesi ile aynı işe yapabilir.
-> Özel Kalıtım(Private Inheritance)
   Bu tür bir kalıtımda sanal olmayan fonksiyonlar yer alır. Var olan bir kodun tekrar kullanımını sağlamak için kullanılır.

   Bunlardan, en sık kullanılanı genel kalıtımdır. Çünkü, özel kalıtım büyük projelerde kullanılır. Böylece programın hızı arttırılabilir. Örneğin, bir oyun sektöründe C++ dilinin en sık kullanılan özelliği sınıflar kullanılır. Yalnız, her zaman genel kalıtım kullanmazlar.
   Kalıtımdan bu kadar bahsettik... Şimdi kalıtımın nasıl tanımlanacağını görelim. Örnek olarak A ve B sınıfları kullanılmıştır:

class A
{
   ...
   ...
   ...
};

class B: public A
{
   ...
   ...
   ...
};

   Burada biz genel kalıtım örneğini görüyoruz. Böyle bir örnekte B sınıfı A sınıfının özelliklerini içerir. A sınıfında protected anahtar sözcüğü kullanılan üyeler A sınıfından türeyen tüm sınıflarda kullanılabilir.
   C++ dilinde çoklu kalıtım özelliği vardır. Örneğin bir sınıf hem A, hem de B sınıfından türeyebilir. Yukarıdaki sınıflara bir de C sınıfı ekleyerek bu olayı görelim.,:

class C: public A, public B
{
   ...
   ...
   ...
};

   Burada tanımladığımız C sınıfı hem A hem de B sınıfının özelliklerini içermektedir. Kalıtım olayı zevkli görünsede C++ dili, kalıtımda bazı kısıtlamalar koymuştur. Bu kısaltmaları henüz görmek için çok erkendir. Biz şimdilik şunu bilsek yeter:

-> Temel sınıfın yapıcısı ilk olarak çalıştırılır. Türetilen sınıfların yapıcı belli bir sıraya göre çalıştırılır. Yokedicilerde ise en son türetilen sınıfın yokedicisi çalıştırılır ve temel sınıfın yokedicisi ise en son çalışır.

   Bu tanıma göre A, B ve C sınıflarına ilişkin bir örnek yapalım ve yapıcıların ve yokedicilerin mantığını anlayalım.

Örnek:

#include <iostream>

using namespace std;

class A
{
    public:
        A()
        {
            cout<<"A sınıfına ait yapıcı çalıştırıldı..."<<endl;
        }

        ~A()
        {
            cout<<"A sınıfına ait yokedici çalıştırıldı..."<<endl;
        }
};

class B:public A
{
    public:
        B()
        {
            cout<<"B sınıfına ait yapıcı çalıştırıldı..."<<endl;
        }

        ~B()
        {
            cout<<"B sınıfına ait yokedici çalıştırıldı..."<<endl;
        }
};

class C:public B
{
    public:
        C()
        {
            cout<<"C sınıfına ait yapıcı çalıştırıldı..."<<endl;
        }

        ~C()
        {
            cout<<"C sınıfına ait yokedici çalıştırıldı..."<<endl;
        }
};

int main()
{
    A a;    //A sınıfına ait a nesnesi
    B b;    //B sınıfına it b nesnesi
    C c;    //C sınıfına ait C nesnei

    return 0;
}


Çıktı:

A sınıfına ait yapıcı çalıştırıldı...
A sınıfına ait yapıcı çalıştırıldı...
B sınıfına ait yapıcı çalıştırıldı...
A sınıfına ait yapıcı çalıştırıldı...
B sınıfına ait yapıcı çalıştırıldı...
C sınıfına ait yapıcı çalıştırıldı...
C sınıfına ait yokedici çalıştırıldı...
B sınıfına ait yokedici çalıştırıldı...
A sınıfına ait yokedici çalıştırıldı...
B sınıfına ait yokedici çalıştırıldı...
A sınıfına ait yokedici çalıştırıldı...
A sınıfına ait yokedici çalıştırıldı...


   Bu örnekte bir şey daha görüyoruz.  A sınıfından türetilen bir sınıf A sınıfına ait yapıcı ve yokedicileri de çalıştırabilmektedir. Bunun nedeni başta belittiğimiz gibi türetilen sınıf temel sınıfın da özelliklerini taşır.
   Peki, buraya kadar anlattık, çabaladık, örnekler yazdık. Ama biz bu örneklerde sınıflar arası üye kullanmalara sadece protected olayı ile değindik. Kalıtım kullanılan sınıflarda erişim denetimi nasıl olur. Hemen görelim...

-Erişim Denetimi
   Sınıflar arasında iki türlü erşim vardır. Bunlardan ilki, düşey erişim denetimidir. İkincisi ise yatay erşim denetimidir. Bu özellikleri şimdi görelim.

-> Düşey Erişim Denetimi
   Türetilmiş sınıfın, temel sınıfın özel(private) üyelerine doğrudan erişemedği durumlara düşey erişim adı verilir. Örneğin A sınıfına it özel i değişkeni, A sınıfından türetilen bir sınıf tarafından doğrudan erişilemez.
   Bu tür durumlarda daha sonra göreceğimiz friend komutunu kullanacağız. Bir örnek üzerinden olayı açıklayayım:

class A
{
   public:
      A();

   private:
      int/color] i;
};

class B: public A
{
   public:
      B();

      void fonk();
};

   Burada B sınıfına ait fonk adlı fonksiyon, A sınıfın i elemanına erişemez. Böyle bir ifade derleyici tarafından hata ile sonuçlanır.


Not: Bir sınıfa ait protorip fonksiyonlar şu şekilde sınıf dışında doldurulabilirler:

<fonk. Veri tipi> <sınıf adı>::<fonk. İsmi>()
{
   ...
   ...
   ...
}


   Yukarıdaki nota göre bir önceki örneğimizdeki B sınıfına ait fonk adlı fonksiyonumuzu sınıf dışında dolduralım.

void A :: fonk()
{

   i=0;

   cout<<i<<endl;

}


   Az önce dediğimiz gibi böyle bir ifade tanımladığımızda derleyici tarafından hata verecektir. Çünkü i elemanı A sınıfının özel elemanıdır.

-> Yatay Erişim Denetimi
   Kısa ve öz anlatmak gerekirse, yatay erişim denetimi sınıf adı ve erişim operatörüyle temel sınıfa erişir. Örneğin:

class A
{
   public:
      A();
      int/color] i;
};

class B: public A
{
   public:
      B();

      void fonk();
};

   Burada i elemanına şu fonksiyon tanımlamasında erişebiliriz.

void A :: fonk()
{

   A::i=0;

   cout<<A::i<<endl;

}


   Burada i elemanına kolaylıkla erişebiliriz. Unutmadan söyleyeyim, "Temel sınıfa ait public ve protected elemanlar türetilmiş sınıfın public ve protected elemanları gibi davranılır." Bu olaya göre erişim olayını az çok anladık.
   Şu ana kadar sınıfları henüz bitirmedik. Daha pek çok anahtar sözcük bulunmaktadır. Kalıtım olayını açıklarken pek fazla örnek kullanmadım. Çünkü şu ana kadar öğrendiklerimizle pek bir şey yazamayız.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..