---
title: 'Ad Alanları ve Kod Düzeni'
source: 'https://academia.sh/tr/kurslar/cpp-temelleri/ad-alanlari-ve-kod-duzeni'
course: 'C++ Temelleri ve Nesne Tasarımı'
language: tr
updated: '2026-09-26T03:02:46+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Aynı ada sahip iki farklı ad alanındaki sembolün, nitelikli adla her zaman kendi tanımına ulaştığını ölçer'
    - 'Bir using bildiriminin yeni bir sembol kurmadığını, var olan sembole yerel bir erişim yolu açtığını gösterir'
    - 'İç içe bir ad alanına iki farklı erişim yolunun (tam ad, takma ad) hep aynı değişkene ulaştığını doğrular'
---

# Ad Alanları ve Kod Düzeni

Aynı ada sahip iki sembolün ad alanlarıyla nasıl ayrıştığının, bir using bildiriminin ve bir ad alanı takma adının yeni bir sembol değil, var olana bir erişim yolu olduğunun ölçümü.

Önceki ders `HataNesnesi::kopya_sayaci`'nin tek bir çeviri biriminde tanımlı `static`
bir üye olarak her çağrıda aynı sayacı paylaştığını gösterdi — ölçü sınıf ve nesne
sınırlarındaydı. Bu ders sınırı bir üst düzeye taşıyor: **ad alanları**. İki farklı
kütüphane ya da modül aynı ismi (`hesapla`, `Arac`) kullanmak isteyebilir; ad alanları
bu çakışmayı, her sembolü kendi ad alanının içine yerleştirerek çözüyor. Bu, kursun
başından beri ölçülen "hangi nesneyle çalışıyor" sorusundan farklı bir eksen: burada
nesne değil, **sembolün kendisi** — bir isim hangi tanıma karşılık geliyor — ölçülüyor.
Ölçü sorusu yine benzer bir kalıp izliyor — bir ifade hangi sembolle çalışıyor — ama
artık sınıf ya da nesne değil, bir isim ve onu barındıran ad alanı ölçülüyor. Kod
düzeni açısından bunun karşılığı basit: bir kütüphane, birbiriyle ilişkili adları tek
bir ad alanının altına toplayarak hem çakışmayı önlüyor hem de o adların nereden
geldiğini okuyan için belirginleştiriyor.

## Aynı Ada Sahip İki Farklı Sembol: Ad Alanları Ayırıyor

`kara` ve `deniz` ad alanlarının ikisi de `hesapla` adında bir işlev tanımlıyor. Nitelikli
adla (`kara::hesapla`, `deniz::hesapla`) çağrıldıklarında, bunlar gerçekten iki farklı
işlev mi, yoksa bir şekilde aynı sembole mi çözülüyor?

```cpp
// ad_alani_ayni_isim.cpp — ad alanlari ayni isimli iki farkli sembolu ayristiriyor
#include <iostream>

namespace kara {
int hesapla(int taban) {
    return taban * 2;
}
}

namespace deniz {
int hesapla(int taban) {
    return taban * 3;
}
}

int main() {
    std::cout << "kara::hesapla(5) sonucu " << kara::hesapla(5) << "\n";
    std::cout << "deniz::hesapla(5) sonucu " << deniz::hesapla(5) << "\n";

    int (*kara_ptr)(int) = kara::hesapla;
    int (*deniz_ptr)(int) = deniz::hesapla;

    std::cout << std::boolalpha
              << "kara::hesapla ile deniz::hesapla ayni islev mu "
              << (kara_ptr == deniz_ptr) << "\n";

    return 0;
}
```

```
kara::hesapla(5) sonucu 10
deniz::hesapla(5) sonucu 15
kara::hesapla ile deniz::hesapla ayni islev mu false
```

**CB16.** `kara::hesapla(5)` ve `deniz::hesapla(5)` farklı sonuçlar veriyor (10 ve 15) —
aynı isim, iki bağımsız gövde. `kara_ptr == deniz_ptr` karşılaştırması bunu işlev
işaretçisi düzeyinde doğruluyor: **false**, çünkü ikisi gerçekten farklı iki sembol.
Ad alanı olmasaydı, aynı imzalı iki `hesapla` aynı çeviri biriminde tanımlanamaz, bir
yeniden tanımlama hatası verirdi. (M11/K03'ün Kütüphane Üretimi dersinde ölçülen
`static`/`extern` bağlantı, bir sembolün bir dosyaya mı hapsolduğunu yoksa dosyalar
arasında mı paylaşıldığını belirliyordu; burada ad alanı aynı bağlantıya sahip iki
sembolü **adlarıyla** ayrıştırıyor — aynı sorunun farklı bir mekanizmadan çözümü.)
Sınıf **kendisi**: nitelikli bir ad (`kara::hesapla`) her zaman kendi ad alanındaki
tikel sembole ulaşıyor, başka bir ad alanındaki eş adlı sembole hiç karışmadan.

## `using` Bildirimi Yeni Bir Sembol Kurmuyor, Var Olana Erişim Açıyor

`kullan` işlevi içinde `using kara::hesapla;` yazıldığında, ortaya çıkan yerel `hesapla`
adı yeni bir sembol mü, yoksa `kara::hesapla`'ya açılan bir erişim yolu mu?

```cpp
// ad_alani_using.cpp — using bildirimi yeni sembol degil, var olana erisim yolu aciyor
#include <iostream>

namespace kara {
int hesapla(int taban) {
    return taban * 2;
}
}

void kullan() {
    using kara::hesapla;
    int (*yerel_ptr)(int) = hesapla;
    int (*dogrudan_ptr)(int) = kara::hesapla;

    std::cout << std::boolalpha
              << "using ile erisilen hesapla dogrudan kara::hesapla ile ayni mi "
              << (yerel_ptr == dogrudan_ptr) << "\n";
}

int main() {
    kullan();
    return 0;
}
```

```
using ile erisilen hesapla dogrudan kara::hesapla ile ayni mi true
```

**CB17.** `using kara::hesapla;` `kullan` işlevi içinde `hesapla` adını nitelemeden
kullanmayı sağlıyor, ama işaret ettiği şey değişmiyor — `yerel_ptr` (nitelemeden
alınan) ile `dogrudan_ptr` (`kara::hesapla` ile doğrudan alınan) aynı işlev
işaretçisini taşıyor, **true**. `using` bildirimi bir kopya çıkarmıyor, yeni bir işlev
de kurmuyor; yalnız derleyiciye "bu nitelenmemiş ad, şu nitelenmiş sembole karşılık
gelsin" diyor. Sınıf **kendisi**: `using` sonrası nitelenmemiş çağrı, nitelenmiş
çağrıyla tam olarak aynı sembole ulaşıyor.

## İç İçe Bir Ad Alanına İki Farklı Erişim Yolu

`sirket::filo` iç içe bir ad alanı. `arac_sayisi`'ne bir işlev tam nitelenmiş adla, bir
başka işlev bir ad alanı takma adıyla (`namespace f = sirket::filo;`) erişiyor. İkisi
de aynı değişkene mi ulaşıyor?

```cpp
// ad_alani_ic_ice.cpp — tam nitelenmis ad ve takma ad ayni degiskene ulasiyor
#include <iostream>

namespace sirket::filo {
int arac_sayisi = 12;
}

void* birinci_erisim() {
    return static_cast<void*>(&sirket::filo::arac_sayisi);
}

void* ikinci_erisim() {
    namespace f = sirket::filo;
    return static_cast<void*>(&f::arac_sayisi);
}

int main() {
    std::cout << std::boolalpha
              << "tam nitelenmis adla ve takma adla erisilen degiskenin ayni olup olmadigi "
              << (birinci_erisim() == ikinci_erisim()) << "\n";
    return 0;
}
```

```
tam nitelenmis adla ve takma adla erisilen degiskenin ayni olup olmadigi true
```

**CB18.** `namespace sirket::filo { ... }` C++17'nin iç içe ad alanı sözdizimiyle tek
satırda iki katman açıyor. `birinci_erisim` `arac_sayisi`'ne tam nitelenmiş adla
ulaşıyor; `ikinci_erisim` önce `f`'yi `sirket::filo`'nun bir **takma adı** olarak
tanımlayıp `f::arac_sayisi` üzerinden ulaşıyor. İki erişim yolunun döndürdüğü adresler
karşılaştırıldığında **true**: takma ad da, tıpkı `using` bildirimi gibi, yeni bir
değişken kurmuyor, var olan tek `arac_sayisi`'ne kısaltılmış bir yol açıyor. Sınıf
**kendisi**: erişim yolu ne kadar farklı görünürse görünsün (tam ad, takma ad,
`using`), hepsi aynı tikel sembole ulaşıyor.

## Adsız Ad Alanı: Sembolü Kendi Birimine Hapsetmek

İki farklı çeviri birimi, her biri kendi adsız (anonim) ad alanı içinde, aynı isimli
(`deger`) bir işlev tanımlıyor. İki birim ayrı ayrı derlenip bağlandığında bu isim
çakışması bir bağlama hatası mı çıkarıyor, yoksa her birim kendi tanımını mı koruyor?

```cpp
// ad_alani_ic_baglanti_birim_a.cpp — adsiz ad alani icindeki sembol bu birime ozgu, disaridan gorunmuyor
namespace {
int deger() { return 111; }
}

int birim_a_deger() {
    return deger();
}
```

```cpp
// ad_alani_ic_baglanti_birim_b.cpp — ayni isimli baska bir adsiz ad alani sembolu, farkli birimde, cakismiyor
namespace {
int deger() { return 222; }
}

int birim_b_deger() {
    return deger();
}
```

```cpp
// ad_alani_ic_baglanti_ana.cpp — iki farkli birimdeki ayni isimli adsiz ad alani sembolu cakismadan derlenip baglaniyor
#include <iostream>

int birim_a_deger();
int birim_b_deger();

int main() {
    std::cout << "birim_a_deger() sonucu " << birim_a_deger() << "\n";
    std::cout << "birim_b_deger() sonucu " << birim_b_deger() << "\n";
    return 0;
}
```

```
birim_a_deger() sonucu 111
birim_b_deger() sonucu 222
```

**CB41.** İki birim de kendi `deger()`'ini çağırıyor ve her biri kendi değerini
döndürüyor — **111** ve **222**, birbirine hiç karışmadan. Adsız bir ad alanı içindeki
her sembol, derleyici tarafından o çeviri birimine özgü, dışarıdan görünmeyen bir isme
dönüştürülüyor; bu yüzden iki ayrı `.cpp` dosyası aynı adı taşıyan bir `deger()`
tanımlasa bile bağlayıcı bunu bir çakışma olarak görmüyor. Bu, `M11/K03`'ün ölçtüğü
`static` bağlantıyla aynı sonucu veriyor — bir sembolü bir dosyaya hapsetmek — ama
adsız ad alanı bunu yalnız işlevler için değil, sınıflar ve değişkenler için de aynı
sözdizimiyle sağlıyor. Sınıf **kendisi**: `birim_a_deger()` içindeki `deger` adı,
yalnız `birim_a`'nın kendi tanımına ulaşıyor; `birim_b`'nin `deger`'iyle hiç
karışmıyor.

## using Bildirimi Tek Sembolü Açıyor, using Yönergesi Tüm Ad Alanını

CB17 `using kara::hesapla;` bir **bildirimdi** — tek bir sembolü nitelemeden erişilebilir
kıldı. `using namespace kara;` bir **yönerge** — bütün ad alanını açar. Aynı ad
alanının iki işlevinden (`hesapla`, `ikile`) yalnız biri bildirimle içeri alınırsa,
diğerine hâlâ nitelenmiş adla mı ulaşmak gerekiyor; yönergeyle ikisine de nitelemesiz
mi ulaşılıyor?

```cpp
// ad_alani_bildirim_vs_yonerge.cpp — using bildirimi tek sembolu aciyor, using yonergesi ad alaninin tamamini aciyor
#include <iostream>

namespace kara {
int hesapla(int taban) { return taban * 2; }
int ikile(int taban) { return taban * 2; }
}

void sadece_bildirim() {
    using kara::hesapla; // yalniz hesapla nitelemesiz erisilebilir hale geliyor
    std::cout << "sadece_bildirim: hesapla(5) = " << hesapla(5) << "\n";
    std::cout << "sadece_bildirim: kara::ikile(5) = " << kara::ikile(5) << "\n";
}

void tum_ad_alani() {
    using namespace kara; // kara'nin tum sembolleri nitelemesiz erisilebilir hale geliyor
    std::cout << "tum_ad_alani: hesapla(5) = " << hesapla(5) << "\n";
    std::cout << "tum_ad_alani: ikile(5) = " << ikile(5) << "\n";
}

int main() {
    sadece_bildirim();
    tum_ad_alani();
    return 0;
}
```

```
sadece_bildirim: hesapla(5) = 10
sadece_bildirim: kara::ikile(5) = 10
tum_ad_alani: hesapla(5) = 10
tum_ad_alani: ikile(5) = 10
```

**CB42.** `sadece_bildirim` içinde `hesapla(5)` nitelemesiz çağrılabiliyor, ama
`ikile` hâlâ `kara::ikile(5)` diye nitelenmek **zorunda** — bildirim yalnız adını
verdiğiniz sembolü açıyor, `kara`'nın geri kalanına dokunmuyor. `tum_ad_alani` içinde
ise `using namespace kara;` sonrası hem `hesapla(5)` hem `ikile(5)` nitelemesiz
çağrılabiliyor — yönerge, ad alanının **tamamını** arama kapsamına ekliyor. İkisi de
aynı iki işleve ulaşıyor (her ikisi de 10 döndürüyor), fark sonuçta değil, hangi
adların nitelemesiz kullanılabilir hale geldiğinde. Sınıf **kendisi**: bildirim ve
yönerge farklı **kapsam genişliğiyle** aynı sembollere erişim açıyor, sembollerin
kendisini değiştirmiyor.

## Çok Birimli Başlık/Kaynak Ayrımı: inline Aynı Tanımın Tekrarına İzin Veriyor

Bir başlık dosyasına yazılıp birden çok `.cpp` dosyasına dahil edilen bir işlev, o
kadar dosya sayısınca **tekrar tekrar** tanımlanmış olur — normal bir işlev bunu tek
tanım kuralına (ODR) aykırı bulur. `inline` anahtar sözcüğü bu tekrarı gerçekten
meşrulaştırıyor mu?

```cpp
// ad_alani_inline_baslik_birim1.cpp — baslik dosyasindan geldigi varsayilan inline islev, bu birimde tanimlaniyor
inline int cift(int x) {
    return x * 2;
}

int birim1_cift(int x) {
    return cift(x);
}
```

```cpp
// ad_alani_inline_baslik_birim2.cpp — ayni inline islevin token'i token'ina ozdes tanimi, baska bir birimde tekrarlaniyor
inline int cift(int x) {
    return x * 2;
}

int birim2_cift(int x) {
    return cift(x);
}
```

```cpp
// ad_alani_inline_baslik_ana.cpp — iki farkli birimdeki ozdes inline tanim, tek tanim kuralini ihlal etmeden derlenip baglaniyor
#include <iostream>

int birim1_cift(int x);
int birim2_cift(int x);

int main() {
    std::cout << "birim1_cift(21) sonucu " << birim1_cift(21) << "\n";
    std::cout << "birim2_cift(21) sonucu " << birim2_cift(21) << "\n";
    return 0;
}
```

```
birim1_cift(21) sonucu 42
birim2_cift(21) sonucu 42
```

**CB43.** İki ayrı çeviri birimi, `cift`'i **birbirinden bağımsız olarak** ama
**token'i token'ına özdeş** biçimde tanımlıyor — tıpkı bir başlık dosyasının iki
`.cpp`'ye dahil edilmesini simüle ediyor. Program başarıyla derlenip bağlanıyor ve her
iki birim de aynı sonucu üretiyor: **42**. `inline`, tek tanım kuralına bir istisna
açıyor: bir işlev birden çok çeviri biriminde tanımlanabilir, **yeter ki her tanım
birebir aynı olsun**. Bu, adsız ad alanının (CB41) çözümünün tam tersi bir strateji —
adsız ad alanı sembolü **gizleyerek** çakışmayı önlüyordu, `inline` ise sembolü
**paylaşarak** ve tanımların aynılığını bir sözleşme hâline getirerek önlüyor. İki
tanım birbirinden farklı olsaydı (örneğin biri `x * 2`, diğeri `x * 3` döndürseydi),
program standarda göre biçimsiz (ill-formed) olurdu ve derleyicinin bunu bildirmesi
gerekmezdi (no diagnostic required) — derleyici bunu her zaman yakalayamaz, bu yüzden burada
hiç çalıştırılmadı; yalnız kuralına uyan, aynı tanımın tekrarlandığı durum ölçüldü.
Sınıf **kendisi**: `cift`, iki birimde de aynı sembole karşılık geliyor, birden fazla
kopya değil, tek bir sözleşmenin iki yerde tutulan aynı ifadesi.

## static ile Paylaşılan (extern) Sembol Arasındaki Karşıtlık

CB41 adsız ad alanıyla iç bağlantı sağladı. `static` anahtar sözcüğü dosya kapsamında
aynı etkiyi doğrudan veriyor. Bir işlevi `static` yapmak onu gerçekten dosyaya
hapsediyor mu; buna karşılık hiç `static` ya da adsız ad alanı kullanılmadan tanımlanan
sıradan bir işlev (varsayılan bağlantısı `extern`) başka bir birimden gerçekten
çağrılabiliyor mu?

```cpp
// ad_alani_baglanti_birim1.cpp — static ic baglantili sembol bu birime ozgu, extern (varsayilan) sembol disari acik
static int ic_deger() {
    return 7;
}

int disa_acik_deger() {
    return 700;
}

int birim1_ic_deger_kullan() {
    return ic_deger();
}
```

```cpp
// ad_alani_baglanti_birim2.cpp — ayni isimli baska bir static sembol, farkli birimde, cakismadan var oluyor
static int ic_deger() {
    return 9;
}

int birim2_ic_deger_kullan() {
    return ic_deger();
}
```

```cpp
// ad_alani_baglanti_ana.cpp — static sembol her birime hapsoluyor, extern (varsayilan) sembol tum birimlerden dogrudan cagrilabiliyor
#include <iostream>

int birim1_ic_deger_kullan();
int birim2_ic_deger_kullan();
int disa_acik_deger();

int main() {
    std::cout << "birim1_ic_deger_kullan() sonucu " << birim1_ic_deger_kullan() << "\n";
    std::cout << "birim2_ic_deger_kullan() sonucu " << birim2_ic_deger_kullan() << "\n";
    std::cout << "ana birimden dogrudan cagrilan disa_acik_deger() sonucu " << disa_acik_deger() << "\n";
    return 0;
}
```

```
birim1_ic_deger_kullan() sonucu 7
birim2_ic_deger_kullan() sonucu 9
ana birimden dogrudan cagrilan disa_acik_deger() sonucu 700
```

**CB44.** `birim1` ve `birim2`'nin kendi `static ic_deger()`'leri, CB41'deki adsız ad
alanı örneğiyle birebir aynı sonucu veriyor: **7** ve **9**, birbirine karışmadan —
`static`, dosya kapsamındaki bir işlevi de tıpkı adsız ad alanı gibi iç bağlantılı
kılıyor. Ama `disa_acik_deger()` hiç `static` ya da adsız ad alanı içinde değil;
varsayılan bağlantısı **extern**, ve bu yüzden yalnız bildirilerek (`int
disa_acik_deger();`) ana birimden **doğrudan** çağrılabiliyor — **700**, kendi
biriminde tanımlanan tek nesneye ulaşıyor. Üç mekanizmanın üçü de bu derste ölçüldü:
adsız ad alanı (CB41) ve `static` (burada) sembolü dosyaya hapsediyor, `inline`
(CB43) sembolü paylaşıp tanımların aynı kalmasını zorunlu kılıyor, sıradan `extern`
bağlantı ise sembolü tek bir tanımda toplayıp her yerden erişilebilir kılıyor. Sınıf
**kendisi**: her üç mekanizma da aynı isim çakışması sorununu, sembolün **görünürlük
kapsamını** değiştirerek çözüyor; sembolün kendisi hep tikel kalıyor.

## Sınırlayıcı Ölçüm

Bu derste ölçülen çok birimli örnekler, gerçek bir başlık dosyasını (`.h`) birden
çok `.cpp`'ye `#include` etmek yerine, aynı tanımı elle iki kaynak birimine
kopyalayarak simüle etti — önişlemcinin `#include` sırasında yaptığı metinsel
kopyalamanın kendisi bu derste ayrıca ölçülmedi. Argümana bağlı arama (ADL, `std::cout
<<` gibi bir işleci niteleme yazmadan bulan mekanizma) bu dersin kapsamı dışında;
burada her çağrı ya nitelenmiş adla ya da açık bir `using` ile yapıldı. Tek tanım
kuralının **ihlal edildiği** durum — iki birimde birbirinden farklı, `inline`
olmayan iki tanımın aynı dışa açık isimle çakışması — bağlama hatası ya da tanımsız
davranışla sonuçlanacağı için hiç çalıştırılmadı; yalnız kurala **uyan** durumlar
ölçüldü. Bir ad alanının kendisinin (işlevlerinden bağımsız olarak) birden çok
dosyada `namespace kara { ... }` bloklarıyla genişletilmesi de ayrıca gösterilmedi;
burada ad alanları hep tek dosya içinde tanımlı kaldı, yalnız onların **içindeki**
sembollerin bağlantı türü çok birimli test edildi.

## Özet

- İki farklı ad alanındaki aynı isimli işlevler bağımsız sembollerdir; nitelikli adla
  (`kara::hesapla`) her zaman kendi tanımına ulaşılıyor.
- İşlev işaretçisi karşılaştırması bunu doğruluyor: `kara::hesapla` ile `deniz::hesapla`
  aynı işlev değil.
- Bir `using` bildirimi yeni bir sembol kurmuyor; nitelenmemiş adı var olan nitelikli
  sembole bağlıyor — sınıf **kendisi**.
- Bir ad alanı takma adı (`namespace f = sirket::filo;`) da aynı ilkeyle çalışıyor:
  yeni bir değişken kurmuyor, var olana kısaltılmış bir erişim yolu açıyor.
- Tam nitelenmiş ad, `using` ve takma ad — üçü de aynı tikel sembole ulaşıyor; farklı
  olan yalnız yazım biçimi.

## Sonraki Adım

Bu ders boyunca `static_cast<void*>(...)` sıkça kullanıldı, ama `static_cast`'in ne
garanti ettiği ya da bir sınıfın kendi dönüşüm kurallarını nasıl tanımlayabileceği hiç
açılmadı — yalnız adres karşılaştırmak için bir araç olarak kullanıldı. Kursun kapanış
dersi, Tip Dönüşüm İşleçleri, bunu doğrudan ele alıyor: bir sınıfın kendi tipinden başka
bir tipe nasıl örtük ya da açık bir dönüşüm sunabileceğini, ve böyle bir dönüşüm
çağrıldığında ortaya çıkan değerin özgün nesneyle mi, yoksa ondan türetilmiş yeni bir
nesneyle mi çalıştığını ölçüyor.
