---
title: 'Tip Dönüşüm İşleçleri'
source: 'https://academia.sh/tr/kurslar/cpp-temelleri/tip-donusum-islecleri'
course: 'C++ Temelleri ve Nesne Tasarımı'
language: tr
updated: '2026-09-26T03:02:46+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'static_cast ile bir taban referansına dönüşümün yeni bir nesne kurmadığını, aynı adresi parça olarak andığını ölçer'
    - "Aynı static_cast'ın hedef değer tipine dönüştüğünde nesneyi dilimleyerek yeni bir kopya kurduğunu gösterir"
    - "dynamic_cast'ın başarısız aşağı dönüşümde işaretçi için nullptr, referans için std::bad_cast verdiğini doğrular"
    - "const_cast ve reinterpret_cast'ın da yeni bir nesne kurmadığını, var olan nesneye farklı bir erişim yolu açtığını gösterir"
---

# Tip Dönüşüm İşleçleri

static_cast, dynamic_cast, const_cast ve reinterpret_cast'ın hedef tipine göre bir referansa parça olarak mı yoksa yeni bir nesneye kopya olarak mı eriştiğinin ölçümü.

Önceki ders `using` bildiriminin ve ad alanı takma adının yeni bir sembol kurmadığını,
var olan sembole yerel bir erişim yolu açtığını gösterdi — ölçü ad alanı sınırındaydı.
Bu ders sınırı bir düzey daha indiriyor: **tip dönüşüm işleçleri**. Bir `Termometre`
nesnesini `static_cast` ile tabanı `Olcer`'e dönüştürdüğümüzde soru aynı kalıyor —
`t` hangi nesneyi anıyordu, dönüşüm hangi nesneyi veriyor? Cevap işlecin adına değil,
**hedef tipe** bağlı: aynı `static_cast`, hedef bir referans olduğunda `t`'nin içindeki
alt nesneyi anıyor; hedef bir değer olduğunda yepyeni bir nesne kuruyor.

## Tabana Dönüştürülen Referans

`Termometre`, `Olcer`'den türüyor. `t`'yi `const Olcer&`'e `static_cast` ile
dönüştürdüğümüzde derleyici yeni bir nesne kurmuyor; `t`'nin içindeki `Olcer`
alt nesnesine daha dar bir tipten bakan bir referans üretiyor. Bu referansın
adresi `t`'nin adresiyle aynı aralıkta kalıyor — çünkü temel sınıf alt nesnesi
türetilmiş nesnenin bir parçası.

```cpp
// taban-referans.cpp — static_cast ile referans donusumu yeni nesne kurar mi
#include <cstdio>

class Olcer {
public:
    virtual ~Olcer() = default;
    void oku() const { std::printf("olcer oku cagrildi\n"); }
};

class Termometre : public Olcer {
public:
    int derece() const { return derece_; }
private:
    int derece_ = 20;
};

int main() {
    Termometre t;
    const Olcer& taban = static_cast<const Olcer&>(t);

    taban.oku();
    std::printf("ayni adres mi %s\n",
        (static_cast<const void*>(&taban) == static_cast<const void*>(&t)) ? "evet" : "hayir");
    return 0;
}
```

```text
olcer oku cagrildi
ayni adres mi evet
```

**CB45.** `taban`, `t` içindeki `Olcer` alt nesnesini anıyor; `oku()` çağrısı yeni
bir nesne üzerinde değil, `t`'nin kendi parçası üzerinde çalışıyor. `&taban` ile
`&t`'nin aynı adres aralığında çıkması bunu doğruluyor — dönüşüm bir kurucu
çağırmadı, yalnız `t`'ye bakan tipi daralttı. Bu ifadenin sınıfı **parça**.

## Değerle Dönüşüm: Aynı İşleç, Farklı Sınıf

Aynı `t`'yi bu kez hedefi bir referans değil bir **değer** olacak şekilde
`static_cast<Olcer>(t)` ile dönüştürelim. İşleç adı aynı — `static_cast` — ama
hedef tip artık bir referans değil, `Olcer`'in kendisi. Derleyici burada `t`'nin
`Olcer` alt nesnesini kopyalayarak yepyeni, bağımsız bir `Olcer` nesnesi kuruyor.

```cpp
// deger-donusumu.cpp — static_cast deger hedefte yeni nesne kurar mi
#include <cstdio>

class Olcer {
public:
    virtual ~Olcer() = default;
    void oku() const { std::printf("olcer oku cagrildi\n"); }
};

class Termometre : public Olcer {
public:
    int derece() const { return derece_; }
private:
    int derece_ = 20;
};

int main() {
    Termometre t;
    Olcer kopya = static_cast<Olcer>(t);

    kopya.oku();
    std::printf("ayni adres mi %s\n",
        (static_cast<const void*>(&kopya) == static_cast<const void*>(&t)) ? "evet" : "hayir");
    return 0;
}
```

```text
olcer oku cagrildi
ayni adres mi hayir
```

**CB46.** `kopya`, `t`'den bağımsız yeni bir `Olcer` nesnesi; `&kopya` ile `&t`
farklı adreslerde çıkıyor. Bu, önceki bölümdeki `static_cast<const Olcer&>(t)`
ile aynı işleç olmasına rağmen tamamen farklı bir sonuç: burada `t`'nin
`Termometre`'ye özgü kısmı (`derece_`) atılıyor, yalnız `Olcer` kısmı kopyalanıyor
— bu, **nesne dilimleme**. Bu ifadenin sınıfı **kopya**.

## Dinamik Dönüşüm: Gerçek Tipe Göre Karar

`static_cast` hedef tipe körü körüne güvenir; derleme anında karar verir.
`dynamic_cast` ise çalışma anında nesnenin gerçek tipine bakar — taban
referansının ardındaki nesne gerçekten istenen türetilmiş tipte değilse
dönüşüm başarısız olur. İşaretçi hedefinde başarısızlık `nullptr` döner;
referans hedefinde bir istisna fırlatır.

```cpp
// dinamik-donusum.cpp — dynamic_cast basarisiz asagi donusumde ne verir
#include <cstdio>
#include <typeinfo>

class Olcer {
public:
    virtual ~Olcer() = default;
};

class Termometre : public Olcer {
public:
    int derece() const { return derece_; }
private:
    int derece_ = 20;
};

class Barometre : public Olcer {
public:
    int basinc() const { return basinc_; }
private:
    int basinc_ = 1013;
};

int main() {
    Termometre t;
    Olcer& taban = t;

    Barometre* p = dynamic_cast<Barometre*>(&taban);
    std::printf("isaretci donusumu basarili mi %s\n", p ? "evet" : "hayir");

    try {
        Barometre& b = dynamic_cast<Barometre&>(taban);
        (void)b;
        std::printf("referans donusumu yakalandi mi hayir\n");
    } catch (const std::bad_cast&) {
        std::printf("referans donusumu yakalandi mi evet\n");
    }
    return 0;
}
```

```text
isaretci donusumu basarili mi hayir
referans donusumu yakalandi mi evet
```

**CB47.** `taban`'ın ardındaki gerçek nesne bir `Termometre`; `Barometre`
değil. `dynamic_cast<Barometre*>` bunu çalışma anında fark edip `nullptr`
döndürüyor — bir istisna fırlatmıyor, sadece "burada yok" diyor. Aynı
başarısızlık referans hedefinde `std::bad_cast` fırlatıyor; burada yalnız
yakalandığı yazdırılıyor, `what()`'in metni değil — mesajın kesin biçimi
kütüphane uygulamasına bağlı, dersin ölçtüğü şey değil. `p` `nullptr` olduğu
için burada üretilmiş bir nesne yok; başarısız bir `dynamic_cast` ne kopya
ne de parça verir, elde hiçbir şey kalmaz.

## Sabitliği Kaldırmak: const_cast

`const_cast` yalnız bir referansın ya da işaretçinin sabitlik niteliğini
değiştirir; hedef tip aynı sınıf kalır, yeni bir nesne kurulmaz. Aşağıdaki
`gozden_gecir`, kendisine `const` bir referansla gelen nesneyi işaretlemek
için sabitliği bir kez kaldırıyor:

```cpp
// const-cast.cpp — sabitligi kaldirmak yeni nesne kurar mi
#include <cstdio>

class Olcer {
public:
    void isaretle() { isaretlendi_ = true; }
    bool isaretlendi() const { return isaretlendi_; }
private:
    bool isaretlendi_ = false;
};

static void gozden_gecir(const Olcer& o) {
    const_cast<Olcer&>(o).isaretle();
}

int main() {
    Olcer o;
    gozden_gecir(o);
    std::printf("isaretlendi mi %s\n", o.isaretlendi() ? "evet" : "hayir");
    return 0;
}
```

```text
isaretlendi mi evet
```

**CB48.** `const_cast<Olcer&>(o)`, `o`'nun kendisine bakan, yalnız sabitlik
niteliği kaldırılmış bir referans veriyor — ne kopya ne parça, `o`'nun
**kendisi**. Bunun güvenli olmasının koşulu `o`'nun asıl nesnesinin gerçekten
`const` olarak tanımlanmamış olması; `main`'deki `o` sabit değil, bu yüzden
`isaretle()` çağrısı tanımsız davranışa girmiyor. Asıl `const` bir nesne
üzerinde aynı çağrı tanımsız davranış olurdu — bu ders böyle bir çağrıyı
yazmıyor da çalıştırmıyor da.

## Bit Örüntüsünü Yeniden Yorumlamak: reinterpret_cast

`reinterpret_cast` en gevşek dönüşüm: hedef tipin kaynak tiple hiçbir ilişkisi
aranmaz, yalnız aynı bit örüntüsü farklı bir tipten okunur. Garanti edilen tek
şey, aynı tipe geri dönüşün orijinal değere eşit çıkması — ara değerin kendisi
taşınabilir bir anlam taşımaz, bu yüzden bu ders onu yazdırmıyor, yalnız
gidiş-dönüş eşitliğini ölçüyor.

```cpp
// yeniden-yorumlama.cpp — reinterpret_cast gidis-donus esitligi
#include <cstdio>
#include <cstdint>

int main() {
    int deger = 42;
    int* p = &deger;

    std::uintptr_t sayisal = reinterpret_cast<std::uintptr_t>(p);
    int* geri = reinterpret_cast<int*>(sayisal);

    std::printf("gidis donus esit mi %s\n", (geri == p) ? "evet" : "hayir");
    return 0;
}
```

```text
gidis donus esit mi evet
```

**CB49.** `reinterpret_cast` de yeni bir nesne kurmuyor; `p`'nin taşıdığı bit
örüntüsünü önce bir tamsayı, sonra tekrar işaretçi olarak okuyor. `geri == p`
eşitliği aynı adresin geri geldiğini gösteriyor — ama bu garanti yalnızca
aynı tipe dönen gidiş-dönüş için geçerli; ara `sayisal` değerinin taşıdığı
sayının kendisi platforma bağlı ve dersin konusu değil.

Peki bir C tarzı dönüşüm — `(Olcer)t`, `(Olcer&)t` gibi — bu dört işleçten
hangisine çözülüyor? Derleyici sırayla dener: önce `const_cast`, sonra
`static_cast`, sonra `const_cast` ile birleşmiş `static_cast`, en sonunda
`reinterpret_cast`. İlk anlamlı olan seçiliyor — bu yüzden bir C tarzı
dönüşümün hangi işlece karşılık geldiği, hedef tip ve kaynak tip arasındaki
ilişkiye bakılarak çıkarılabilir, ama okurken bunu görmek `static_cast` ya da
`dynamic_cast` yazmaktan daha zor. Bu ders C tarzı dönüşümü kullanmıyor; adını
yalnız hangi işlece çözüldüğünü göstermek için anıyor.

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

Bu ders dört dönüşüm işlecinin dördünün de **adının** sınıfı belirlemediğini
gösterdi — belirleyen **hedef tip**. Aynı `static_cast`, hedef bir referans
olduğunda `t`'nin içindeki alt nesneyi anıyor (parça), hedef bir değer
olduğunda yeni bir nesne kuruyor (kopya). Bu ders bu ikisini ayrı ayrı ölçtü;
işlecin adına bakıp sınıfı tahmin etmek bu derste hiç yapılmadı.

Hatalı bir `static_cast` ile gerçekte o tipte olmayan bir nesneyi aşağı
dönüştürmek — örneğin `taban`'ın ardındaki nesne bir `Termometre` iken onu
`static_cast<Barometre&>` ile dönüştürmek — tanımsız davranıştır: derleyici
bunu engellemez, çalışma anında da bir denetim yapılmaz. Bu ders böyle bir
çağrıyı yazmadı da çalıştırmadı da; güvenli aşağı dönüşüm için bu dersin
gösterdiği yol `dynamic_cast`'tır. `reinterpret_cast`'ın ürettiği ara
değerlerin platforma bağlı yorumu, `const_cast`'ın gerçekten `const` bir
nesne üzerindeki tanımsız davranışı ve C tarzı dönüşümün çözüm sırasının
derleyiciler arası ayrıntıları da bu dersin dışında kaldı.

## Özet

- `static_cast` ile bir taban referansına dönüşüm yeni bir nesne kurmuyor;
  `t`'nin içindeki alt nesneyi daha dar bir tipten anıyor.
- Aynı `static_cast`, hedef bir değer olduğunda `t`'yi dilimleyerek bağımsız
  yeni bir nesne kuruyor — işleç aynı, sınıf farklı.
- `dynamic_cast` başarısız aşağı dönüşümde işaretçi için `nullptr`, referans
  için `std::bad_cast` veriyor; hiçbir durumda yeni bir nesne kurmuyor.
- `const_cast` ve `reinterpret_cast` da yeni nesne kurmuyor, var olan nesneye
  farklı bir erişim yolu açıyor.
- Bu dersin ölçtüğü ifade — `static_cast<const Olcer&>(t)` ile elde edilen
  taban referansı — **parça** sınıfındadır: `t`'nin kendi adresini, dar bir
  tipten anıyor.

## Kurs Kapanışı

Bu ders, **C++ Temelleri ve Nesne Tasarımı** kursunun son dersiydi. Kurs
boyunca her ders aynı soruyu farklı bir sınırda sordu: bir ifade hangi
nesneyle çalışıyor — kendisiyle mi, bir kopyasıyla mı, bir parçasıyla mı,
yoksa adı olmayan bir geçiciyle mi?

| Ders | Ölçülen ifade | Hangi nesne | Sınırlayıcı ölçüm |
| --- | --- | --- | --- |
| C ve C++ Farkları | `degerle aktarilan yapi` | kopya | Çağrı noktası sınıfı söylemez; karar parametre tipinde |
| Sınıflar ve Erişim Denetimi | `uye islevin this'i` | kendisi | `private` nesneyi değil sınıfın sınırını korur |
| Yapıcılar ve Yıkıcılar | `int'ten kurulan arguman` | geçici | `const` referansa bağlanan geçicinin ömrü uzar |
| RAII | `koruyucunun biraktigi uye` | parça | Kaynağa referans tutan koruyucunun sarkması yalnız anlatıldı |
| Kopyalama ve Atama | `derin kopyalanan tampon` | kopya | Kopyanın derinliği yalnız kopyalayan yapıcının gövdesinden okunur |
| Referanslar | `referansla aktarilan yapi` | kendisi | `const` referans parametre geçiciye de bağlanabilir |
| İşleç Aşırı Yükleme | `a + b sonucu` | geçici | `a + b + c`'de yalnız ara sonuç geçicidir; son sonuç doğrudan `toplam`da kurulur |
| Kalıtım | `taban sinifin islevi` | parça | Tekli ve sanal olmayan kalıtımla sınırlı |
| Sanal Fonksiyonlar ve Sanal Tablolar | `taban referansindan sanal cagri` | kendisi | Değerle atama ve sanal olmayan yıkıcı kapsam dışı |
| Soyut Sınıflar ve Arayüzler | `arayuz uzerinden cagri` | kendisi | Çoklu arayüz kalıtımı bir sonraki derse bırakıldı |
| Çoklu Kalıtım ve Elmas Sorunu | `sanal tabanin alt nesnesi` | parça | Sanal tabana erişimin dolaylılık maliyeti ölçülmedi |
| İstisnalar | `degerle yakalanan istisna` | kopya | `catch(...)` ve `noexcept` içinde fırlatma kapsam dışı |
| Ad Alanları ve Kod Düzeni | `using bildirimiyle anilan nesne` | kendisi | ADL ve `#include` mekaniği kapsam dışı |
| Tip Dönüşüm İşleçleri | `tabana donusturulen referans` | parça | Hatalı `static_cast` aşağı dönüşümü yalnız anlatıldı, çalıştırılmadı |

**5 kendisi · 3 kopya · 4 parça · 2 geçici; var olan 9, yeni 5**

On dört ders boyunca aynı soru on dört farklı sınırda soruldu; cevap hep
işlecin ya da sözdiziminin adına değil, derleyicinin gerçekte ne kurduğuna
bakılarak verildi. Sıradaki kurs bu soruyu bir adım öteye taşıyor: bir nesnenin
sahip olduğu kaynağı ne zaman bıraktığı, bir değeri kopyalamak yerine ne zaman
taşıdığı ve standart kütüphanenin bu taşımayı nasıl kullandığı.
