D Programlama Dili – Programlama dersleri ve D referansı
Ali Çehreli

etiket: [label], kod satırlarına isimler vermeye yarayan olanak
kurucu işlev: [constructor], nesneyi kuran işlev
sonlandırıcı işlev: [destructor], nesneyi sonlandıran işlev
... bütün sözlük



İngilizce Kaynaklar


Diğer




Etiketler ve goto

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.

Not: Aslında etiketler herhangi iki deyimin arasında da bulunabilirler ve bulundukları o noktayı isimlendirmiş olurlar. Ancak bu kullanım yaygın değildir:

    birİfade(); bitiş: başkaİfade();
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:

birinci
üçüncü

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, ve diğer 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ı, scope() deyimleri, vs. gibi olanaklarla sağlanır.

Not: Bu kullanıma C++'ta 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++'ta 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ğinden 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ırlar. 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 atlandığında, henüz kurulmadıklarından 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 hazır olmayan nesne

Derleyici bu hatayı önler:

Error: goto skips declaration of variable deneme.main.s
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.

case bölümlerinde kullanımı

goto'nun case bölümlerinde nasıl kullanıldıklarını switch ve case bölümünde görmüştük:

Özet