const ref Parametreler ve const Üye İşlevler
Bu derste üye işlevlerin const nesnelerle de kullanılabilmeleri için nasıl const olarak işaretlenmeleri gerektiğini göreceğiz. Burada her ne kadar yapıları kullanıyor olsak da; const üye işlevler sınıflar için de geçerlidir.
const nesneler
Şimdiye kadarki derslerde bazı örneklerde const değişkenler ve nesneler tanımlamış ve const anahtar sözcüğünün nesnelerin değiştirilemez olmalarını sağladığını görmüştük:
const auto okumaSaati = GününSaati(15, 0);
okumaSaati değiştirilemez:
okumaSaati = GününSaati(16, 0); // ← derleme HATASI okumaSaati.dakika += 10; // ← derleme HATASI
Derleyici; const nesneye yeni bir değer atanmasına, bir üyesinin değiştirilmesine, veya herhangi başka bir değişiklik yapılmasına izin vermez. Zaten const olarak işaretlemenin amacı da budur: bazı nesnelerin değerlerinin değişmeyeceği garantisi gerekebilir.
const ref parametreler
const ve immutable dersinde gördüğümüz gibi, immutable nesneler programda kesinlikle değişmeyen nesnelerdir. const nesneler ise belirli bir referans yoluyla, veya belirli bir bağlamda değişmeyen nesnelerdir.
Kendisi aslında const olmayan bir nesne, belirli bir bağlamda değiştirilmeden kullanılabilir. Bunun bir örneği, parametrelerdir. const ref olarak işaretlenen bir parametre, o işlev içinde değiştirilmeyecek demektir:
int toplamSaniye(const ref Süre süre) { return 60 * süre.dakika; }
O işlev, parametresini const olarak işaretleyerek o parametrede değişiklik yapmayacağı garantisini vermiş olur. Derleyici de o nesnenin değiştirilmesine izin vermez:
int toplamSaniye(const ref Süre süre) { süre.dakika = 7; // ← derleme HATASI // ... }
const olmayan ref parametreler
ref parametrelerin işlev içinde değiştirilmemeleri yönünde bir kısıtlama yoktur. O parametreyi değiştirmiyor bile olsalar, bunun garantisini vermedikleri için o işlevlere const nesne gönderilemez:
// süre'yi değiştirmiyor olsa bile const olarak işaretlememiş int toplamSaniye(ref Süre süre) { return 60 * süre.dakika; } // ... const Süre ısınmaSüresi = Süre(3); toplamSaniye(ısınmaSüresi); // ← derleme HATASI
Not: Yukarıdaki kod, bu dersi yazdığım sırada kullandığım derleyicinin (dmd 2.046) bir hatası yüzünden derlenebiliyor. O hata giderildiğinde yukarıdaki kod derleme hatasına neden olacaktır.
Derleyici, const olan ısınmaSüresi nesnesinin toplamSaniye işlevine gönderilmesine izin vermez; çünkü toplamSaniye işlevi, parametresinde değişiklik yapmayacağı garantisini vermemektedir.
const olmayan üye işlevler
Nesneleri değiştirmenin başka bir yolu, üye işlevlerdir. Örneğin GününSaati.ekle işlevi, üzerinde çağrıldığı nesneyi ona bir Süre ekleyerek değiştiriyordu:
struct GününSaati { // ... void ekle(in Süre süre) { dakika += süre.dakika; saat += dakika / 60; dakika %= 60; saat %= 24; } // ... } // ... auto başlangıç = GününSaati(5, 30); başlangıç.ekle(Süre(30)); // başlangıç değişir
const üye işlevler
Bazı üye işlevler, üzerinde çağrıldıkları nesnede değişiklik yapmazlar:
struct GününSaati { // ... string toString() { return format("%02s:%02s", saat, dakika); } // ... }
toString'in işi, nesneyi string olarak ifade etmektir; nesnenin kendisinde bir değişiklik yapmaz.
Üye işlevlerin nesnede bir değişiklik yapmayacakları garantisi, parametre listesinden sonra yazılan const sözcüğü ile belirtilir:
struct GününSaati { // ... string toString() const { return format("%02s:%02s", saat, dakika); } }
O const, nesnenin o işlev içinde değiştirilmeyeceği garantisini sağlar.
Böylece derleyici toString'i const nesnelerle de çağırabilir. Çünkü toString const olarak işaretlenmemiş olsa, const nesneleri yazdıramamak gibi yapay bir kısıtlamayla karşı karşıya kalınır:
struct GününSaati { // ... // const olarak işaretlenmemiş (yanlış tasarım) string toString() { return format("%02s:%02s", saat, dakika); } } // ... const auto başlangıç = GününSaati(5, 30); string dizgiOlarak = başlangıç.toString(); // ← derleme HATASI
Şimdiye kadarki derslerde gördüğümüz toString üye işlevlerinin bu kısıtlama yüzünden yanlış tasarlandıklarını söyleyebiliriz.
Ne zaman kullanmalı
toString gibi, nesnede değişiklik yapmayan üye işlevleri her zaman için const olarak işaretleyin:
struct GününSaati { // ... string toString() const { return format("%02s:%02s", saat, dakika); } }
Böylece yapının ve sınıfın kullanışlılığı gereksizce kısıtlanmamış olur. Bundan sonraki derslerdeki kodlar da buna uygun olarak tasarlanacaklar.
Not: İşlevin nesnede değişiklik yapmayacağını garanti eden bu const anahtar sözcüğü aslında işlevin tanımından önce de yazılabilir:
// üsttekiyle aynı şey const string toString() { return format("%02s:%02s", saat, dakika); }
Dönüş türüyle karışma riski olduğu için ben const anahtar sözcüğünü bu şekilde değil, yukarıda gösterdiğim gibi parametre listesinden sonra yazmayı yeğliyorum.
D.ershane
Forum
Wiki
Projeler
Tanıtım
İletişim
Hakları