11 MAYIS 2017
PAZAR
16.07
C++ Kapsama ve Ad Alanları (Namespace)

Kapsama alanları C++'a özgü bir durum değildir. Her kodlama dilinde olduğu gibi değişkenlerin tanımlandıkları alanlar değişkenlerin kullanım alanlarını doğrudan etkilerler.

 

Bir değişken eğer herhangi bir sınıfa veya fonksiyona bağlı olmaksızın, yani herhangi bir bloğun dışında, kullanılmışsa o değişken GLOBAL değişken olarak adlandırılır.

Herhangi bir blok içerisinde veya daha açık bir tabir ile herhangi bir fonksiyonun veya sınıfın içerisinde tanımlanan değişkenler LOCAL değişken olarak adlandırılır.

Aşağıdaki kod parçamızda bu duruma ait 2 değişken kullanarak bir örnek hazırladım.

int x;

int fonksiyon() {
	int y;
	y = 10;
}

int main(){
	
	x = 10; // Global olan x değişkeninde herhangi bir problem yok
	y = 6; // Local olan y değişkeni main() fonksiyonunda tanımlanmadığı için hata verir
	
}

Kod parçasında x ve y adını verdiğimiz 2 değişken bulunuyor. Bu değişkenlerden x diğer iki fonksiyonun dışında GLOBAL olarak tanımlanmış durumda ve bu sebeple global olan x değişkenini istediğimiz bir fonksiyon içerisinde kullanabiliriz. Öte yandan fonksiyon() isimli fonksiyon içerisinde tanımlanan y değişkeninin bir başka fonksiyonda tanımlı olmadığı için hata vermesi beklenen durum olacaktır. Bu sebeple int main() içerisinde bir y değişkeni tanımlanmamış ve global olarak bir y değişkeni olmadığı için programımız burada hata verecektir.

Buna rağmen y değişkenini kod parçamızdan kaldırıp cout ile ekrana x'i yazdırmak istediğimizde, yani;

int x;

int toplamaFonk() {
	int y;
	y = 10;
}

int main(){
	
	x = 10;
	cout << x;
	
}

Bu kod yapısını kullandığımızda x isimli değişkenimiz bir global değişken olduğu için main() fonksiyonu içerisinde x değişkenimize yeni bir değer atayabiliyor ve bu değeri ekrana çıktı olarak verdirebiliyoruz. Sonuç olarak ekranımızda 10 sayısını görüntüleyeceğiz.

Aynı Ad Farklı Veri Tipi

Bu kabul edilemez bir durum. Bir fonksiyon içerisinde farklı veri türüne sahip dahi olsa aynı ad birden fazla kullanılamaz!

int main(){
	int x = 10;
	double x = 5;
	cout << x;
}

Elbette bu durum fonksiyonlar için farklılık göstermektedir. Bu konuda bilgi edinmek için buraya bakabilirsiniz.

Namespaces

Bir blok içerisinde aynı ada sahip yalnızca tek bir nesne olabilir. Namespace bunu baz alarak tasarlanmış ve isim çakışmalarını önleyici bir yapıdır. Namespace içerisinde sınıflar, fonksiyonlar veya değişkenlere yer verilebilir.

namespace isim
{
  int x, y;
}

olarak tanımlanabilir. Buna göre bu alan içerisinde oluşturulan x ve y değişkenlerine ulaşmak için klasik olarak kapsam dışından x veya y yazmak doğru olmaz. Çünkü bir üstteki konuda da bahsettiğimiz gibi her blok kendi içerisindeki elemanlardan sorumludur. Öyleyse biz bu x ve y değişkenine nasıl ulaşabiliriz?

Namespace İçerisindeki Öğeler Ulaşmak

Namespace içerisinde var olan sınıf, fonksiyon veya değişkene ulaşmak için aşağıdaki kod yapısını kullanabiliriz;

isim::sinifAdi
isim::fonksiyonAdi
isim::degiskenAdi

ÖRNEK

3 farklı namespace içerisinde tanımlanan x değerlerini ekrana yazdırın.

ÇÖZÜM

namespace adAlani1 {
	int x = 10;
}
namespace adAlani2 {
	int x = 15;
}
namespace adAlani3 {
	int x = 20;
}

int main() {
	cout << adAlani1::x << endl;
	cout << adAlani2::x << endl;
	cout << adAlani3::x;
}

using Ön Eki

Namespace yapısı içinde belirtilen bir değişkene yukarıdaki örneğimizde olduğu gibi ulaşmak için namespace adını ve ulaşılacak nesneyi belirtiyoruz. Fakat biz bunun yerine örneğin yapımızda x değişkeninin yeniden tanımlanmamasını fakat her defasında da namespace adının yeniden girilmesini istemiyoruz diyelim. Böyle bir durumda using ön ekini kullanıyoruz. Örneğimize şöyle göz atabiliriz;

ÖRNEK

namespace ns1 {
	int x = 50;
	int y = 150;
}

namespace ns2 {
	double x = 10.5;
	double y = 150.5;
}

int main() {	
	using ns1::x;
	using ns2::y;
	cout << x << endl;
	cout << y << endl;
	cout << ns1::y << endl;
	cout << ns2::x << endl;
}

Örnekte de görüldüğü üzere ns1 ve ns2 isimleri ile oluşturulmuş 2 namespace'i içerisinde yer alan x ve y değerlerini çağırarak ekrana yazdırmayı başardık. Bu sayede iki değişkende de aynı isimlere sahip olmasına rağmen ekrana 4 değişkenimizi de yazdırmayı başardık. Genellikle daha komplike durumlarda bu yapının çok fazla işimize yarayacağını söyleyebilirim.

Bu yapıyı kavradıktan sonra aynı olayı daha genel kapsamlı uygulayabiliriz. Yani ns1 alanında yer alan ve int veri tipindeki x ve y değerlerini tamamıyla main içerisine aktarabilmek için yukarıdaki yapıyı biraz değiştirirsek şöyle bir sonuca ulaşırız;

namespace ns1 {
	int x = 50;
	int y = 150;
}

namespace ns2 {
	double x = 10.5;
	double y = 150.5;
}

int main() {	
	using namespace ns1;
	cout << x << endl;
	cout << y << endl;
	cout << ns2::y << endl;
	cout << ns2::x << endl;
}

Bu yapımız sayesinde "using namespace ns1" ile ns1'de yer alan değerlerin hepsini main() fonksiyonumuza çağırmış olduk.

using ile aynı değişken adını çağırmak

using kullanılan yerde üstteki örneğimizi ele alarak ns1 veya ns2 namespace'lerini çağırdıktan sonra içlerinde aynı ada sahip olmalarına rağmen farklı bir yöntem ile ekrana çıktı verdirebildik. Fakat bundan ziyade ikisinde de var olan bir x değişkeni farklı değerlere sahip iken main() fonksiyonumuz içerisinde bu x değerlerini using ile kullanmamız da mümkün olabilir. Bunun için blok yapısını dikkate alarak main içerisinde yeni bir blok oluşturmak en mantıklı çözüm olacaktır.

namespace ns1 {
	int x = 10;
}

namespace ns2 {
	int x = 15;
}

int main() {
	{
		using namespace ns1;
		cout << x << endl;
	}
	
	{
		using namespace ns2;
		cout << x << endl;
	}
}

Kod yapısından da anlaşıldığı üzere main() içerisinde oluşturulan 2 yeni blok yapısı içerisinde namespace öğelerine yer verdik ve aynı değişken adı olan x'e atanmış farklı değerleri ekrana çıktı verdirebildik.

YORUMLAR 0
Bu konuya henüz kimse yorum yapmadı.
İlk yorumu sen yapmak ister misin?
YORUM BIRAK
Şuanda bu yoruma cevap yazıyorsunuz:
İptal Et