Ana sayfa > Programlama > C++ Programlama > İsim alanları (Namespaces)

İsim alanları (Namespaces)

► Detaylı anlatım

C++'da, isim alanlarını temel amacı, isim çakışmalarını önlemek için tanımlayıcıların isimlerini yerel olarak ifade etmektir. İsim alanları kullanılmadığında, farklı yerlerde kullanılan aynı isme sahip değişken, fonksiyon ve sınıflar arasında bir karışıklık yaşanmaktadır. C++ standart kütüphanesi std adlı isim alanı içinde tanımlı olduğundan, bu kütüphanede yer alan bildirimlerin, program içinde yapılan benzer isme sahip diğer bildirimlerle çatışması engellenmektedir. Her programda, bildirimlerimiz için ayrı isim alanları oluşturabiliriz.

İsim alanları kullanımı

İsim alanı oluşturmak için namespace anahtar kelimesini kullanabiliriz. İsim alanı tanımlayarak, global isim alanı içinde belirli bölge ayırmış oluruz.

İsim alanı oluşturmak için kullanılan genel yapı aşağıda gösterilmektedir:

namespace isim-alanı-adı {
  // Bildirimler
}

İsim alanı içinde yer alan bildirimler, tanımlandığı isim alanının kapsamında işlem görür.

Bir isim alanı içinde tanımlanan değişken, fonksiyon ve sınıflara isim alanı içinden doğrudan, isim alanı dışından ise isim alanın ismi :: işlemcisi ve erişim sağlanacak isim alanı üyesinin adı ile birlikte kullanılarak erişim sağlanır.

isim-alanı-adı::üye-adı;

Şimdi, isim alanı bildirimi ve kullanımını bir örnek üzerinde incelemeye çalışalım:


#include <iostream>

using namespace std;

// Global bildirimler
int id;

int kare_al(int deger)
{
  return deger * deger;
}

class sinif
{
  private:
    int priid;
  protected:
    int proid;
  public:
    int pubid;
    sinif(int pid1, int pid2, int pid3)
    {
      priid = pid1; proid = pid2; pubid = pid3;
    }
    void deger_goster()
    {
      cout << priid << " " << proid << " " << pubid << "\n";
    }
};

// İsim alanı bildirimi
namespace ns
{
  int id;

  int kare_al(int deger)
  {
    return deger * deger;
  }

  class sinif
  {
    private:
      int priid;
    protected:
      int proid;
    public:
      int pubid;
      sinif(int pid1, int pid2, int pid3)
      {
        priid = pid1; proid = pid2; pubid = pid3;
      }
      void deger_goster()
      {
        cout << priid << " " << proid << " " << pubid << "\n";
      }
  };
}

int main(void)
{
  // Global olarak tanımlanmış değişken, fonksiyon ve sınıf işlemleri
  sinif nes1(7, 21, 35);
  nes1.deger_goster();

  id = kare_al(21);
  cout << 21 << " değerinin karesi: " << id << "\n";

  // İsim alanı içinde tanımlanmış değişken, fonksiyon ve sınıf işlemleri
  ns::sinif nes2(9, 24, 38);
  nes2.deger_goster();

  ns::id = ns::kare_al(17);
  cout << 17 << " değerinin karesi: " << ns::id << "\n";

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:

7 21 35
21 değerinin karesi: 441
9 24 38
17 değerinin karesi: 289

Program, önce global olarak, id adlı int bir değişken, parametre olarak geçirilen int bir değerin karesini geri döndüren kare_al() adlı bir fonksiyon ve priid adlı private int bir değişken, proid adlı protected int bir değişken, pubid adlı public int bir değişken, bu değişkenlere birer değer atayan bir constructor fonksiyonu ve değişken değerlerini ekrana yazan bir fonksiyon içeren sinif adlı bir sınıf bildirimi yapar. Sonra, yaptığı tüm bildirimleri aynı isme ve yapıya sahip olacak şekilde ns adlı isim alanı içinde yapar.

Önce, global olarak bildirimi yapılan sinif türünden bir nesne oluşturur ve nesne yoluyla deger_goster() fonksiyonu çağırarak sınıf kopyası içinde yer alan değişken değerlerini ekrana yazar. Global olarak tanımlanmış kare_al() fonksiyonu ile 21 değerinin karesini alarak yine global olarak tanımlanmış id int değişkenine atar ve değişken değerini ekrana yazar.

Sonra, aynı işlemleri, sadece değerleri değiştirerek, isim alanı içinde yer alan bildirimlerle gerçekleştirir. İsim alanı içinde yer alan değişken, fonksiyon ve sınıfa erişim için :: işlemcisi kullandığından, global olarak bildirimi yapılmış ve aynı isme sahip olan değişken, fonksiyon ve sınıf ile herhangi bir karışma olmaz.

Bir isim alanı içinde yer alan işlem satırlarında, aynı isim alanı içindeki verilere doğrudan erişim sağlanabilir. Bu durumu bir örnek üzerinde incelemeye çalışalım:


#include <iostream>

using namespace std;

namespace ns
{
  int id=21;

  void deger_goster(void)
  {
    cout << id; // id değişkenine doğrudan erişim sağlanır.
  }
}

int main(void)
{
  ns::deger_goster();

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:

21

Program, bir isim alanı içinde id adlı int bir değişken ve bu değişken değerini ekrana yazan deger_goster() adlı bir fonksiyon bildirimi yapar. Bu fonksiyonu kullanarak değişken değerini ekrana yazar. Fonksiyon içinde id değişkenine doğrudan erişim sağlanmaktadır.

Using ifadesi kullanımı

Bir programda bildirimi yapılan isim alanları içinde yer alan tek bir üye veya tüm üyelere, isim alanı adı ve :: işlemcisi kullanmadan, doğrudan erişim sağlamak için, using ifadesi kullanabiliriz.

using namespace isim-alanı-adı;

using isim-alanı-adı::üye-adı;

Şimdi, using ifadesi kullanımını bir örnek üzerinde incelemeye çalışalım:


#include <iostream>

using namespace std;

namespace ns1
{
  int id;

  int kare_al(int deger)
  {
    return deger * deger;
  }

  class sinif
  {
    private:
      int priid;
    protected:
      int proid;
    public:
      int pubid;
      sinif(int pid1, int pid2, int pid3)
      {
        priid = pid1; proid = pid2; pubid = pid3;
      }
      void deger_goster()
      {
        cout << priid << " " << proid << " " << pubid << "\n";
      }
  };
}

namespace ns2
{
  int id1=7, id2=21;

  void deger_goster(void) {
    cout << id1 << " " << id2;
  }
}

using namespace ns1; // ns1 isim alanı içindeki tüm üyelerin erişime açılması
using ns2::id1;      // ns2 isim alanı içindeki id1 değişkeninin erişime açılması

int main(void)
{
  // ns1 isim alanı içindeki tüm üyelere isim alanı ve :: işlemcisi kullanmadan erişim
  sinif nes(9, 24, 38);
  nes.deger_goster();

  id = kare_al(17);
  cout << 17 << " değerinin karesi: " << id << "\n";

  // ns2 isim alanı içindeki id1 değişkenine isim alanı ve :: işlemcisi kullanmadan erişim
  id1 = 75;
  // ns2 isim alanı içindeki id2 değişkeni ve deger_goster() fonksiyonuna isim alanı ve :: işlemcisi kullanarak erişim
  ns2::id2 = 35;
  ns2::deger_goster();

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:

9 24 38
17 değerinin karesi: 289
75 35

Program, ns1 adlı bir isim alanı içinde, id adlı int bir değişken, parametre olarak geçirilen int bir değerin karesini geri döndüren kare_al() adlı bir fonksiyon ve priid adlı private int bir değişken, proid adlı protected int bir değişken, pubid adlı public int bir değişken, bu değişkenlere birer değer atayan bir constructor fonksiyonu ve değişken değerlerini ekrana yazan bir fonksiyon içeren sinif adlı bir sınıf bildirimi yapar. Sonra, ns2 adlı bir isim alanı içinde, id1 ve id2 adlı iki adet int değişken ve bu değişken değerlerini ekrana yazan deger_goster() adlı bir fonksiyon bildirimi yapar.

Daha sonra, using ifadesini iki defa kullanarak, ns1 isim alanı içindeki tüm üyelerin ve ns2 isim alanı içindeki id1 değişkenini erişime açar.

Önce, ns1 isim alanı içindeki sinif türünden bir nesne oluşturur ve nesne yoluyla deger_goster() fonksiyonu çağırarak sınıf kopyası içinde yer alan değişken değerlerini ekrana yazar. ns1 isim alanı içinde tanımlanmış kare_al() fonksiyonu ile 17 değerinin karesini alarak yine ns1 isim alanı içinde tanımlanmış id int değişkenine atar ve değişken değerini ekrana yazar.

Sonra, :: işlemcisini kullanmadan, ns2 isim alanı içindeki id1 değişkenine 75 değerini atar. :: işlemcisini kullanarak, ns2 isim alanı içindeki deger_goster() fonksiyonu ile id1 ve id2 değişken değerlerini ekrana yazar.