Etiketler
Etiketler, kod satırlarına isimler vermeye ve program akışını bu isimli satırlara yöneltmeye yararlar.
Etiketin isminden ve : karakterinden oluşurlar:
bitiş: // ← bir etiket
Yukarıdaki etiket, tanımlandığı satıra bitiş ismini verir.
goto
İngilizce'de "git" anlamına gelen goto, program akışını ismi belirtilen satıra yönlendirir:
void birİşlev(bool koşul) { writeln("birinci"); if (koşul) { goto bitiş; } writeln("ikinci"); bitiş: writeln("üçüncü"); }
Yukarıdaki işlev, koşul'un true olduğu durumlarda doğrudan bitiş isimli satıra gider, ve "ikinci" yazdırılmaz.
Etiketler ve goto D'ye C'den geçmiştir. goto, yapısal programlamaya aykırı olduğu için C'de bile kaçınılması önerilen bir olanaktır. Doğrudan belirli satırlara yönlendiren goto'lar yerine; while, for, vs. gibi yapısal deyimlerin kullanılması önerilir.
Örneğin yukarıdaki kodun eşdeğeri, şimdiye kadar çoğu kodda gördüğümüz gibi, goto kullanmadan şöyle yazılabilir:
void birİşlev(bool koşul) { writeln("birinci"); if (!koşul) { writeln("ikinci"); } writeln("üçüncü"); }
Buna rağmen goto'nun C dilinde iki tane geçerli kullanımı vardır. Bu kullanımların ikisi de D'de gereksizdir.
D'de gerekmeyen, sonlandırıcı bölge
goto'nun C'deki geçerli bir kullanımı, işlevlerin sonlarına yazılan ve o işlevde ayrılmış olan kaynakların geri verilmesi gibi işlemleri içeren sonlandırıcı bölgedir:
// --- C kodu ---
int birIslev()
{
// ...
if (hata) {
goto bitis;
}
// ...
bitis:
// ... sonlandirma islemleri buraya yazilir ...
return hata;
}
D'de kaynak yönetimi için başka olanaklar bulunduğu için, bu kullanım D'de gereksizdir. D'de sonlandırma işlemleri; çöp toplayıcı, sonlandırıcı işlevler, hata atma düzeneğinin catch ve finally blokları, vs. gibi olanaklarla sağlanır.
Not: Bu kullanıma C++'da da gerek yoktur.
D'de gerekmeyen, iç içe döngülerde kullanımı
goto'nun C'deki diğer geçerli kullanımı, iç içe döngülerin daha dışta olanlarını etkilemektir.
Döngüyü kırmak için kullanılan break, ve döngüyü hemen ilerletmek için kullanılan continue, yalnızca en içteki döngüyü etkiler. C'de ve C++'da dıştaki döngüyü kırmanın bir yolu, döngüden sonraki bir etikete gitmektir; dıştaki döngüyü ilerletmenin bir yolu da, onun hemen içindeki bir etikete gitmektir:
// --- C kodu ---
while (birKosul) {
while (baskaKosul) {
// yalnizca icteki donguyu etkiler
continue;
// yalnizca icteki donguyu etkiler
break;
// distaki icin 'continue' gibi calisir
goto distakiniIlerlet;
// distaki icin 'break' gibi calisir
goto distakindenCik;
}
distakiniIlerlet:
;
}
distakindenCik:
Not: Bu kullanıma C++ programlarında da rastlanabilir.
Aynı durum, iç içe bulunan switch deyimlerinde de vardır; break yalnızca içteki switch'i etkilediği için, dıştakinden de çıkmak için goto kullanılabilir.
D'de goto'nun bu kullanımına da gerek yoktur. Onun yerine, biraz aşağıda göstereceğim döngü etiketleri kullanılır.
goto'nun kurucu işlevleri atlama sorunu
Kurucu işlevler, nesnelerin kuruldukları satırlarda çağrılır. Bunun nedenlerinden birisi, nesnenin kurulması için gereken bilginin henüz mevcut olmaması olabilir. Bir başka neden, belki de hiç kullanılmayacak olan bir nesneyi kurmak için gereksizce zaman ve kaynak harcamamaktır.
Nesnelerin kuruldukları satırlar goto ile atlanabilse, kurulamamış oldukları için hatalı sonuçlar doğuran nesnelerle karşılaşılabilir:
if (koşul) { goto birEtiket; // kurucu işlevi atlar } auto nesne = Yapı(42); // nesnenin kurulduğu satır birEtiket: nesne.birİşlem(); // HATA: belki de kurulmamış olan // nesneyi kullanır
Yukarıdaki koddaki goto ile birEtiket satırına gidilebilse; birİşlem() işlevi, kurulamamış bir nesne üzerinde işletilirdi. Bu yüzden, goto'nun bu tür kullanımı D'de hatalıdır ve yukarıdaki kod bir derleme hatasına neden olur:
Error: cannot goto forward into different try block level
Not: Aynı sorun C++'da da vardır; ama bu konu, C++'da programcının dikkatine bırakılmıştır.
Döngü etiketleri
D'de döngülerden hemen önce etiketler tanımlanabilir. continue ve break anahtar sözcüklerinde de etiket belirtilebilir, ve o döngülerin etkilenmeleri sağlanabilir:
dışDöngü: while (birKoşul) { while (başkaKoşul) { // içteki döngüyü ilerletir continue; // içteki döngüden çıkar break; // dıştaki döngüyü ilerletir continue dışDöngü; // dıştaki döngüden çıkar break dışDöngü; } }
Aynısı switch deyimleri için de geçerlidir. break deyimlerinin dıştaki bir switch'i etkilemesi için o switch deyiminden önce de etiket tanımlanabilir.
Özet
D'de goto'yu kullanmak için hiçbir neden yoktur.
İç içe döngülerden veya switch deyimlerinden hangisinin etkileneceğini belirtmek için break ve continue deyimlerinde etiket belirtilebilir.
D.ershane
Forum
Wiki
Projeler
Tanıtım
İletişim
Hakları