C++/İsim Uzayları

< C++

İsim Alanı Nedir? ( namespace )

C++ dilinde tüm blokların dışında kalan alan global isim alanı olarak adlandırılır. Global isim alanı, programı oluşturan tüm dosyaları dolayısıyla bütün alanları kapsar. Bu alanda bildirilen tüm varlıklar global bilinirlik alanının içindedir. Yani yalnızca bildirildiği kaynak dosyada değil programı oluşturan diğer dosyalarda da bilinebilirdir. Global bilinirlik alanı içinde bildirilmiş varlıkların isimleri farklı olmak zorundadır, çünkü aynı bilinirlik alan içinde aynı isimde iki varlık olamaz. Aynı dosya içinde aynı isimli varlıkların bulunması derleme zamanında hata verirken farklı dosyalarda bulunması da bağlama zamanında hata verir.

Örnek:
// x_cpp dosyası
int miktar;
...
void miktar(); // hata, aynı bilinirlik alnında (global bilinirlik alanı) aynı isimde iki varlık bildirilmiş, derleme zamanında hata verir.
...
// x_h dosyası
int miktar; // hata, aynı bilinirlik alnında aynı isimde iki varlık bildirilmiş, bağlama zamanında hata verir. miktar isimli değişken x_cpp dosyasından bildirilmiştir.
...
void tutar();
...

Global isim alanında yer alan varlıkların isim çakışmalarını önlemek için programcı varlıkların isimlerini değiştirebilir. Bu durumda farklı bir isim bulmak adına varlığın amacını betimleyen isimden uzaklaşılabilir. Mesela bir dizi int değerin toplamını tutacak olan tutar değişkenine farklı bir isim kullanmak okunabilirliği düşürecektir. Daha sonra kodu gözden geçirdiğimizde bu değişkeni bulmak ve anlamak zor olabilir. Belki de programcı kendi tanımladığı tüm varlıklar için bir ön takı kullanmayı seçebilir. Bu durumda isimler uzama eğilimi gösterir ve uzun isimleri yazmak programcı için zahmetli ve hataya daha açıktır. Dahası isim çakışmaları yalnızca programcının kendi oluşturduğu dosyalar için değil başka firma veya şahıslar tarafından üretilmiş olup projede kullanılan kütüphaneler ve diğer dosyalar içinde geçerlidir. Büyük projelerde sayıları çok fazla olan dosyalar için isim çakışması riski de artar.

C++ standartları global isim alanındaki isim çakışmalarını çözmek veya en aza indirmek için namespace mekanizmasını getirmiştir.


İsim Alanı Tanımlaması

namespace namespace_adı {
... // bildirimler, tanımlamalar
}

namespace:İsim alanı tanımlaması namespace anahtar kelimesiyle başlar.
namespace_adı:İsim alanının adıdır ve isimlendirme kurallarına uygun olarak programcı tarafından belirlenir.
küme parantezleri:Küme parantezleri isim alnında kendi içinde tanımlanan varlıkları kapsayan bir alan tanımlar. Noktalı virgülle sonlanmaz.
• namespace (isim alanı) global isim alanında tanımlanmış bir alandır.
• Bir namespace içinde tanımlanmış bütün varlıklar yine globaldir.
• İsim alanları global isim alanında bildirilebilir.
• Bir isim alanı başka bir isim alnının içinde de bildirilebilir.
• Yerel düzeyde isim alanı bildirilemez.
• Bir isim alanı içinde bildirilmiş sınıfların veya prototipi bildirilmiş fonksiyonların tanımlamaları başka bir isim alanında yapılamaz. Ya kendi isim alanında ya da global isim alanında tanımlanabilir.
Örneğin:
namespace A{
void Fonk(); // Fonk fonksiyonun prototipi A isim alanında yapılmış
}
...
namespace B{
void A::Fonk(){ // hata, başka bir namespace de prototipi bildirilmiş bir fonksiyon tanımlaması
}
}
void A::Fonk(){ //geçerli, global isim alanında tanımlanabilir
}

Varlıkların isimlendirilmesini bilgisayardaki dosya ve klasör hiyerarşisine benzetebiliriz. Bir kök dizin içinde birden fazla klasör veya dosya aynı isimde olamaz. Burada kök dizin global isim alanına, klasörler de isim alanlarına denk gelir. Ama kök dizin içinde farklı isimlerdeki klasörlerin içerisinde aynı isimli dosyalar veya klasörler yerleştirilebilir. Örnek olarak dosya.txt isimli dosya hem A klasöründe hem de B klasörü gibi farklı klasörler içinde aynı isimde bulunabilir. Ama yine bir klasörün içinde aynı isimde yalnızca bir dosya olabilir.


İsim Alanının Kapsamı

İsim alanları bir bilinirlik alanıdır. Global isim alanında bir alan tanımlayarak kendi içindeki varlıkları gizler. Bu açıdan bir namespace içindeki tüm varlıkların global düzeydeki varlıklardan tek farkı elemanı olduğu namespace tarafından gizlenmiş olmasıdır. Örnek:
namespace Alan_A{
class miktar{
...
};
int adet;
}
namespace Alan_B{
class miktar{ // geçerlidir
...
};
double pi;
class miktar{ // geçersizdir
...
};
}
Yukarıdaki örnekte miktar sınıfı hem Alan_A hem de Alan_B isim alanlarında tanımlanmıştır. Bu iki namespace iki farklı kapsam oluşturduğuna göre miktar sınıfının tanımlamaları geçerlidir. Alan_B namespace içinde miktar sınıfı ikinci kez bildirilmiştir. Bir kapsam içinde aynı isimli iki varlık bulunamayacağından bildirim geçersizdir. İsim alanları global düzeyde oldukları için gizlediği elamanlarda global düzeydedir ve programı oluşturan tüm dosyalar tarafından erişilebilir. Fakat erişim şekli global varlıklara doğrudan erişilebildiği gibi yapılmaz.

İsim Alanı Elemanlarına Erişim

Bir isim alanı tanımlayıp içindeki elemanlar global düzeyden gizlediğine göre, isim alanının dışından bu elemanlara nasıl erişilecektir? İsim alanındaki varlıkların kullanılabilmesi için derleyiciye kullanılan varlığın hangi isim alanında arayacağını bildirmek gerekir. Eğer bildirilmez ise derleyici ismi önce bulunduğu bilinirlik alnında arar eğer bulamazsa bilinirlik alanını kapsayan diğer bilinirlik alanlarında aramaya devam eder.
• İsim alanı dışından elamanlara erişmek için iki terimli araek konumunda çözünürlük işleci (::) kullanılır.
• Çözünürlük işleci kullanılarak beraber yazılan isimlere nitelenmiş isim (qualified name) denir.
• İsim alanındaki varlıklara dışarıdan ancak nitelenmiş isimle erişilebilir.
Örnek:
namespace ALAN{
class Personel{
...
}
int miktar;
}
...
ALAN::miktar = 500; // geçerli
int Fonk (Personel *PPersonel); // geçersiz
void Fonk1 (ALAN::Personel *PPersonel); // geçerli
Fonk fonksiyonunun parametre değişkeni olan *PPersonel, ALAN isimli namespace in elamanı olan Personel sınıfı türündendir. Nitelendirilmeden kullanıldığı için geçersizdir. Diğer elemanlar nitelendirildiği için geçerlidir.
Örnek:
class Personel{
...
}
namespace ALAN{
class Personel{
...
}
int miktar;
}
...
int Fonk (Personel PPersonel); // geçerli
void Fonk1 (ALAN::Personel PPersonel); // geçerli
Fonk fonksiyonunda bildirilen PPersonel nesnesi, global isim alanında bildirilmiş olan Personel sınıfı türündendir. Derleyici PPersonel nesnesini bulunduğu bilinirlik alanında arayıp bulacağından bildirim geçerlidir.
İsim alanında bildirilen varlıkları nitelendirmeden doğrudan kullanmayı sağlayan bildirimler vardır. Bunlar:
1. using bildirimi
2. using namespace bildirimi
Bir de bu bildirimlerin dışında C++ dilinde mevcut olan ve otomatik olarak uygulanan argümana bağlı isim arama ( Koenig ) özelliği vardır. Koenig isim arama özelliği ayrıca anlatılacaktır.

Bu belgenin yazılması ve düzeltmeler Mehmet ÖZCAN tarafından yapılmıştır...