C++ 'const' Hakkında Bilinmesi Gerekenler

const anahtar kelimesi kullanım açısından karıştırılabilen bir durumdadır. Bundan dolayı kafalardaki karışıklığı gidermek için olabildiğince detaylı bir anlatımla bu duruma açıklık getirmek istedim.

Programlamayı en başta öğrenirken, ilk olarak const sayesinde sabit değişkenler oluşturulduğu öğrenilir.
int main(){
    const int var = 10;
    var = 12;
    return 0;
}
Yukarıdaki main fonksiyonu çalıştırıldığında error: assignment of read-only variable 'var' şeklinde bir hata alınmaktadır. Hatanın sebebi sadece okunabilir olan değişkene atama yapmaya çalışmaktır. Ayrıca en başta var değişkenine oluşturulma esnasında atama yapılmazsa derleyici error: uninitialized const 'var' [-fpermissive] hatası verecektir. Bu şekilde oluşturulan değişkenler program tarafından değiştirilemez.

Kısacası yukarıda yapılan işlem const ile bir değişkenin sabit olduğunu programa bildirmektir. Bu kullanım en basit kullanım şeklidir.
İşaretçilerde const, kulllanım sırasına göre değişken için farklılık gösterir. Şimdi sırasıyla bu sıralamaları derleyici üzerinde test edelim:
int main(){
    int a = 10;
    int b = 5;
    const int *testPtr = &a;
    testPtr = &b;
    *testPtr = 10;
    return 0;
}
İlk olarak a ve b adında integer değişkenler tanımlandı ve sırasıyla 10 ve 5 değerleri bu değişkenlere atandı. Sonrasında ilk olarak const bildirimi yapılmak üzere integer türünde pointer tanımlandı. Bu işaretçiye a değişkeninin referansı atandı, buna göre işaretçi a değişkeninin adresindeki değeri gösterecek. Yukarıdaki const int *testPtr şeklinde yapılan tanımlamaya göre integer değişkenin gösterdiği değer adres değiştirilmediği sürece değişmez. Bunun sebebi const bildirimidir. Fakat testPtr işaretçisinin referansı değiştirilirse gösterdiği değer farklı adresteki değeri göstereceğinden, değişmiş görünecektir. testPtr = &b; şeklinde referans değişikliği yapıldığında derleyici herhangi bir hata vermeyecektir. Çünkü const bildirimi onun için geçerli değil. *testPtr değerinin gösterdiği değer 5, biz bu değeri değiştirmek için *testPtr = 10; şeklinde değer ataması yaparsak, derleyici error: assignment of read-only location '* testPtr' hatası verecektir.

Aşağıdaki gibi bir pointer kullanımı olsaydı yine yukarıdaki ile aynı sonuçları elde ederiz.
int const *testPtr = &a;
Eğer kodda aşağıdaki gibi int * const testPtr; şeklinde bir değişiklik yapılırsa.
int main(){
    int a = 10;
    int b = 5;
    int * const testPtr = &a;
    *testPtr = 10;
    testPtr = &b;
    return 0;
}
Böyle bir durumda işaretçinin gösterdiği değer değiştirilebilirken, işaret ettiği değer değiştirilemez. Derleyici bu referans değişikliğine karşı error: assignment of read-only variable 'testPtr' hatasını verir.

Hem işaretçinin gösterdiği değerin hemde referans adresinin değişmemesi istenirse kullanım aşağıdaki gibi olmalı:
int main(){
    int a = 10;
    int b = 5;
    const int * const testPtr = &a;
    *testPtr = 10;
    testPtr = &b;
    return 0;
}
Kod çalıştırıldığında derleyici iki tane hata verecektir, bu hatalar: error: assignment of read-only location '*(const int*)testPtr' ve error: assignment of read-only variable 'testPtr' hatalarıdır.

Nesne ve Üye Fonksiyonlarında 'const' Kullanımı

Sınıftan oluşturulan nesne const olarak bildirilirse nesneye ait değerler sonrasında değiştirilemez. Bu nesne sadece const bildirimine sahip fonksiyonları çağırabilir.
class Example{
    private:
        int value;
    public:
        Example(): value(0) {}
        void set(int v) {value = v;}
        int get() {return value;}
};

int main(){
    const Example e;
    e.set(10);    
    return 0;
}
Yukarıdaki örnekte Example sınıfından oluşturulan e nesnesi const olarak bildirilmiştir. Nesneye ait value üye değişkenine varsayılan olarak 0 değeri atanmıştır. set fonksiyonu ile value değeri değiştirilmek istenirse derleyici error: passing 'const Example' as 'this' argument discards qualifiers [-fpermissive] hata verecektir. Derleyici ayrıca note: in call to 'void Example::set(int)' şeklinde bilgi vermektedir. Eğer const ile bir nesne oluşturulursa, o nesne sadece const bildirimine sahip üye fonksiyonlarına ulaşabilir. Yukarıdaki kod aşağıdaki değişikliğe uğratılırsa:
class Example{
    private:
        int value;
    public:
        Example(): value(0) {}
        void set(int v) const {value = v;}
        int get() {return value;}
};

int main(){
    const Example e;
    e.set(10);
    return 0;
}
Bu kez çalıştırıldığında derleyici error: assignment of member 'Example::value' in read-only object hatasını verecektir.

Bir diğer durum ise üye fonksiyonlarında 'const' kullanımıdır. Üye fonksiyonlarında const bildirimi yapılması, o fonksiyonun nesne üzerinde bir değişiklik yapamayacağını ve const bildirimi yapılmayan fonksiyonlara erişemeyeceği anlamına gelmektedir. Üye fonksiyonda const bildirimi fonksiyonun parametresinden sonra ve kod gövdesinden önce 'const' yazılması ile mümkündür.
void set(int v) const {value = v;}

Hiç yorum yok:

Yorum Gönderme