<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-21T06:05:37+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">C# İstisna Yönetimi: try-catch-finally ile Hataları Kontrol Altına Almak</title><link href="https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak/" rel="alternate" type="text/html" title="C# İstisna Yönetimi: try-catch-finally ile Hataları Kontrol Altına Almak" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak/"><![CDATA[<p>Bir uygulamanın hiç hata üretmemesi neredeyse imkânsızdır; önemli olan, hata ortaya çıktığında sistemin nasıl davrandığıdır. C# istisna yönetimi, beklenmeyen durumları ana program akışından ayırarak uygulamanın kontrollü biçimde tepki vermesini sağlar. Dosya bulunamaması, ağ bağlantısının kesilmesi veya geçersiz kullanıcı girdisi artık birer felaket değil, yönetilebilir senaryolardır.
``</p>
<h2 id="i̇stisna-nedir">İstisna nedir?</h2>

<p>İstisna, program çalışırken normal akışı bozan olağan dışı bir durumu temsil eden nesnedir. C# içerisindeki bütün istisnalar doğrudan veya dolaylı olarak <code class="language-plaintext highlighter-rouge">System.Exception</code> sınıfından türetilir.</p>

<p>Bir işlemin başarısız olma olasılığını $P(E)$, hatanın sisteme vereceği zararı da $C(E)$ ile gösterirsek basitleştirilmiş risk hesabı şöyle yazılabilir:</p>

\[R = P(E) \times C(E)\]

<p>İstisna yönetimi hatanın oluşma ihtimalini her zaman azaltmaz; fakat $C(E)$ değerini düşürerek hatanın uygulamanın tamamına yayılmasını engeller.</p>

<table>
  <thead>
    <tr>
      <th>Yapı</th>
      <th>Görevi</th>
      <th>Ne zaman çalışır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">try</code></td>
      <td>Riskli kodu çevreler</td>
      <td>Her denemede</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">catch</code></td>
      <td>Belirli istisnayı yakalar</td>
      <td>Eşleşen hata oluştuğunda</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">finally</code></td>
      <td>Kaynak temizliği yapar</td>
      <td>Hata olsa da olmasa da</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">throw</code></td>
      <td>İstisna oluşturur veya yeniden fırlatır</td>
      <td>Koşul sağlandığında</td>
    </tr>
  </tbody>
</table>

<h2 id="try-catch-finally-mimarisi">try-catch-finally mimarisi</h2>

<p>Aşağıdaki örnek bir dosyayı okumayı dener, olası hataları türlerine göre izole eder ve işlem sonunda bilgi verir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span>
<span class="p">{</span>
    <span class="kt">string</span> <span class="n">metin</span> <span class="p">=</span> <span class="n">File</span><span class="p">.</span><span class="nf">ReadAllText</span><span class="p">(</span><span class="s">"ayarlar.json"</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">metin</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">FileNotFoundException</span> <span class="n">ex</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Dosya bulunamadı: </span><span class="p">{</span><span class="n">ex</span><span class="p">.</span><span class="n">FileName</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">UnauthorizedAccessException</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Dosyaya erişim yetkiniz yok."</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">IOException</span> <span class="n">ex</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Girdi/çıktı hatası: </span><span class="p">{</span><span class="n">ex</span><span class="p">.</span><span class="n">Message</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">finally</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Dosya okuma denemesi tamamlandı."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">catch</code> blokları özelden genele doğru sıralanmalıdır. Önce <code class="language-plaintext highlighter-rouge">Exception</code> yakalanırsa daha özel bloklara sıra gelmez. Ayrıca her yerde genel <code class="language-plaintext highlighter-rouge">Exception</code> yakalayıp hatayı sessizce yutmak, yangın alarmının pilini çıkarmaya benzer: ortam sessizleşir ama yangın devam eder.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Özel istisnayı yakalamak</td>
      <td>Anlamlı ve hedefli tepki sağlar</td>
      <td>Daha fazla blok gerektirebilir</td>
    </tr>
    <tr>
      <td>Genel <code class="language-plaintext highlighter-rouge">Exception</code> yakalamak</td>
      <td>Son savunma hattı oluşturur</td>
      <td>Gerçek hata nedenini gizleyebilir</td>
    </tr>
    <tr>
      <td>Hatayı yutmak</td>
      <td>Akış görünürde sürer</td>
      <td>Teşhis ve veri güvenliği zorlaşır</td>
    </tr>
    <tr>
      <td>Loglayıp yeniden fırlatmak</td>
      <td>Katmanlar arası görünürlük sağlar</td>
      <td>Aynı hata birden fazla kez loglanabilir</td>
    </tr>
  </tbody>
</table>

<p>Bir istisnayı aynı çağrı yığını bilgisiyle yeniden göndermek için <code class="language-plaintext highlighter-rouge">throw;</code> kullanılmalıdır. <code class="language-plaintext highlighter-rouge">throw ex;</code> ifadesi yığın izini değiştirerek hatanın gerçek kaynağını bulmayı zorlaştırabilir.</p>

<h2 id="özel-hata-sınıfları">Özel hata sınıfları</h2>

<p>İş kuralları için hazır istisnalar her zaman yeterince açıklayıcı değildir. Örneğin stok miktarının yetersiz olması teknik değil, alan odaklı bir problemdir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">YetersizStokException</span> <span class="p">:</span> <span class="n">Exception</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">MevcutStok</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="nf">YetersizStokException</span><span class="p">(</span><span class="kt">string</span> <span class="n">mesaj</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mevcutStok</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">mesaj</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">MevcutStok</span> <span class="p">=</span> <span class="n">mevcutStok</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">SiparisVer</span><span class="p">(</span><span class="kt">int</span> <span class="n">istenen</span><span class="p">,</span> <span class="kt">int</span> <span class="n">stok</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">istenen</span> <span class="p">&gt;</span> <span class="n">stok</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">YetersizStokException</span><span class="p">(</span>
            <span class="s">"İstenen miktar stoktan fazla."</span><span class="p">,</span> <span class="n">stok</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu sınıf, hataya yalnızca mesaj değil, <code class="language-plaintext highlighter-rouge">MevcutStok</code> gibi yapılandırılmış bağlam da ekler. Üst katman böylece kullanıcıya uygun bildirim gösterebilir veya işlemi başka bir depoya yönlendirebilir.</p>

<h2 id="sağlam-kullanım-ilkeleri">Sağlam kullanım ilkeleri</h2>

<ul>
  <li>İstisnaları yalnızca gerçekten olağan dışı durumlarda kullanın; normal kontrol akışını <code class="language-plaintext highlighter-rouge">throw</code> ile kurmayın.</li>
  <li><code class="language-plaintext highlighter-rouge">ArgumentException</code>, <code class="language-plaintext highlighter-rouge">InvalidOperationException</code> ve <code class="language-plaintext highlighter-rouge">FileNotFoundException</code> gibi uygun hazır türleri tercih edin.</li>
  <li>Hataları bağlam bilgisiyle loglayın; parola ve erişim anahtarı gibi hassas verileri kaydetmeyin.</li>
  <li><code class="language-plaintext highlighter-rouge">IDisposable</code> kaynaklarında mümkünse <code class="language-plaintext highlighter-rouge">using</code> kullanın; derleyici gerekli temizliği güvenli biçimde oluşturur.</li>
  <li>Kullanıcıya sade mesaj, geliştiriciye ise ayrıntılı log sağlayın.</li>
</ul>

<p>Doğru tasarlanmış istisna yönetimi hataları yok etmez; onları sınırlar, görünür kılar ve uygulamanın güvenli biçimde toparlanmasına yardımcı olur. Kısacası <code class="language-plaintext highlighter-rouge">try-catch-finally</code>, kodun emniyet kemeridir: kazayı engellemeyebilir ama sonucunu ciddi ölçüde kontrol eder.</p>

<p><img src="/img/c-istisna-yonetimi-11.svg" alt="c-istisna-yonetimi-11" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="csharp" /><category term="exception" /><category term="hata-yönetimi" /><category term="try-catch" /><category term="dotnet" /><category term="özel-istisnalar" /><summary type="html"><![CDATA[Bir uygulamanın hiç hata üretmemesi neredeyse imkânsızdır; önemli olan, hata ortaya çıktığında sistemin nasıl davrandığıdır. C# istisna yönetimi, beklenmeyen durumları ana program akışından ayırarak uygulamanın kontrollü biçimde tepki vermesini sağlar. Dosya bulunamaması, ağ bağlantısının kesilmesi veya geçersiz kullanıcı girdisi artık birer felaket değil, yönetilebilir senaryolardır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-istisna-yonetimi-11.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-istisna-yonetimi-11.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta Statik ve Dinamik Bağlamayı Karıştırınca Patlayan Tasarımlar</title><link href="https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar/" rel="alternate" type="text/html" title="C++’ta Statik ve Dinamik Bağlamayı Karıştırınca Patlayan Tasarımlar" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar/"><![CDATA[<p>C++’ta bir fonksiyon çağrısının hangi gövdeye gideceği her zaman göründüğü kadar basit değildir. Derleyici bazen kararı derleme zamanında verir, bazen de çalışma zamanındaki gerçek nesne türüne bakar. Statik ve dinamik bağlamayı aynı tasarım içinde bilinçsizce karıştırmak; yanlış fonksiyonların çağrılmasına, kaynak sızıntılarına ve “Ama bu sınıfı ezmiştim!” şaşkınlığına yol açabilir.</p>

<p><img src="/img/cta-statik-ve-16.svg" alt="cta-statik-ve-16" /></p>

<p>``</p>

<h2 id="bağlama-tam-olarak-nedir">Bağlama tam olarak nedir?</h2>

<p>Bağlama, bir çağrı ifadesinin çalıştırılacak fonksiyon gövdesiyle eşleştirilmesidir. Statik bağlamada karar, değişkenin derleme zamanındaki türüne göre verilir. Dinamik bağlamada ise <code class="language-plaintext highlighter-rouge">virtual</code> mekanizması üzerinden nesnenin çalışma zamanındaki gerçek türü kullanılır.</p>

<p>Bunu kabaca şöyle düşünebiliriz:</p>

\[secim = f(T_{statik}, T_{dinamik}, virtual)\]

<p>Fonksiyon sanal değilse çoğunlukla $T_{statik}$ belirleyicidir. Sanal fonksiyon çağrısında ise uygun koşullarda $T_{dinamik}$ devreye girer.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Statik bağlama</th>
      <th>Dinamik bağlama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Karar zamanı</td>
      <td>Derleme zamanı</td>
      <td>Çalışma zamanı</td>
    </tr>
    <tr>
      <td>Temel ölçüt</td>
      <td>İfadenin statik türü</td>
      <td>Nesnenin gerçek türü</td>
    </tr>
    <tr>
      <td>Tipik araçlar</td>
      <td>Overload, normal metot</td>
      <td><code class="language-plaintext highlighter-rouge">virtual</code>, <code class="language-plaintext highlighter-rouge">override</code></td>
    </tr>
    <tr>
      <td>Maliyet</td>
      <td>Genellikle doğrudan çağrı</td>
      <td>Genellikle sanal tablo erişimi</td>
    </tr>
    <tr>
      <td>Yaygın risk</td>
      <td>Yanlış overload seçimi</td>
      <td>Hatalı yaşam döngüsü tasarımı</td>
    </tr>
  </tbody>
</table>

<h2 id="hata-1-sanal-olmayan-yıkıcı">Hata 1: Sanal olmayan yıkıcı</h2>

<p>Polimorfik bir taban sınıfın yıkıcısını sanal yapmamak, en tehlikeli karışıklıklardan biridir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Kaynak</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="o">~</span><span class="n">Kaynak</span><span class="p">()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Kaynak kapandı</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Dosya</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Kaynak</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="o">~</span><span class="n">Dosya</span><span class="p">()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Dosya kapandı</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Kaynak</span><span class="o">*</span> <span class="n">kaynak</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Dosya</span><span class="p">;</span>
    <span class="k">delete</span> <span class="n">kaynak</span><span class="p">;</span> <span class="c1">// Tanımsız davranış!</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">delete</code> işlemi taban işaretçisi üzerinden yapıldığı için yıkıcının dinamik davranması gerekir. Çözüm basittir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">virtual</span> <span class="o">~</span><span class="n">Kaynak</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</code></pre></div></div>

<p>Bir sınıfta sanal metot varsa yıkıcının da genellikle sanal olması beklenir.</p>

<h2 id="hata-2-varsayılan-argümanların-sanal-olduğunu-sanmak">Hata 2: Varsayılan argümanların sanal olduğunu sanmak</h2>

<p>Sanal fonksiyonun gövdesi dinamik, varsayılan argümanı ise statik olarak seçilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">Bildirim</span> <span class="p">{</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">gonder</span><span class="p">(</span><span class="kt">int</span> <span class="n">oncelik</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">oncelik</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">Alarm</span> <span class="o">:</span> <span class="n">Bildirim</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">gonder</span><span class="p">(</span><span class="kt">int</span> <span class="n">oncelik</span> <span class="o">=</span> <span class="mi">9</span><span class="p">)</span> <span class="k">override</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">oncelik</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Alarm</span> <span class="n">alarm</span><span class="p">;</span>
    <span class="n">Bildirim</span><span class="o">&amp;</span> <span class="n">b</span> <span class="o">=</span> <span class="n">alarm</span><span class="p">;</span>
    <span class="n">b</span><span class="p">.</span><span class="n">gonder</span><span class="p">();</span> <span class="c1">// Alarm::gonder çalışır, fakat argüman 1 olur.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Ortaya hibrit bir sonuç çıkar: gövde alt sınıftan, değer taban sınıftan gelir. Varsayılan değeri tek yerde tanımlamak veya parametresiz ayrı bir sanal olmayan arayüz kullanmak daha güvenlidir.</p>

<h2 id="hata-3-kurucuda-sanal-çağrı">Hata 3: Kurucuda sanal çağrı</h2>

<p>Kurucu sırasında nesnenin alt sınıf bölümü henüz hazır değildir. Bu nedenle taban kurucusundan yapılan sanal çağrı, alt sınıf sürümüne gitmez:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="nc">Motor</span> <span class="p">{</span>
    <span class="n">Motor</span><span class="p">()</span> <span class="p">{</span> <span class="n">baslat</span><span class="p">();</span> <span class="p">}</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="nf">baslat</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/* taban davranışı */</span> <span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">TurboMotor</span> <span class="o">:</span> <span class="n">Motor</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">baslat</span><span class="p">()</span> <span class="k">override</span> <span class="p">{</span> <span class="cm">/* turbo henüz hazır olmayabilir */</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Nesneyi oluşturduktan sonra çağrılan bir <code class="language-plaintext highlighter-rouge">initialize()</code> metodu veya fabrika fonksiyonu kullanmak daha açık bir yaşam döngüsü sağlar.</p>

<h2 id="hata-4-nesne-dilimleme">Hata 4: Nesne dilimleme</h2>

<p>Alt sınıf nesnesini değer olarak taban türe kopyalamak dinamik tür bilgisini keser:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">calistir</span><span class="p">(</span><span class="n">Motor</span> <span class="n">motor</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Kopyalama ve dilimleme</span>
    <span class="n">motor</span><span class="p">.</span><span class="n">baslat</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bunun yerine <code class="language-plaintext highlighter-rouge">Motor&amp;</code>, <code class="language-plaintext highlighter-rouge">Motor*</code> veya uygun bir akıllı işaretçi kullanılmalıdır.</p>

<h2 id="sağlam-tasarım-kontrol-listesi">Sağlam tasarım kontrol listesi</h2>

<ul>
  <li>Ezilen her metoda <code class="language-plaintext highlighter-rouge">override</code> ekleyin.</li>
  <li>Polimorfik tabanlarda sanal yıkıcı kullanın.</li>
  <li>Sanal metotlarda farklı varsayılan argümanlardan kaçının.</li>
  <li>Kurucu ve yıkıcılarda sanal dispatch’e güvenmeyin.</li>
  <li>Polimorfik nesneleri değer yerine referans veya işaretçiyle taşıyın.</li>
  <li>Overload ile override kavramlarını aynı şey sanmayın.</li>
</ul>

<p>Kısacası <code class="language-plaintext highlighter-rouge">virtual</code>, tasarıma sihir serpiştiren bir kelime değildir. Hangi kararın derleyiciye, hangisinin çalışma zamanına bırakıldığını açıkça belirlemek gerekir; aksi hâlde kod derlenir, çalışır ve tam en kötü anda yanlış şeyi yapar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="binding" /><category term="polimorfizm" /><category term="oop" /><category term="tasarım-hataları" /><category term="virtual" /><summary type="html"><![CDATA[C++’ta bir fonksiyon çağrısının hangi gövdeye gideceği her zaman göründüğü kadar basit değildir. Derleyici bazen kararı derleme zamanında verir, bazen de çalışma zamanındaki gerçek nesne türüne bakar. Statik ve dinamik bağlamayı aynı tasarım içinde bilinçsizce karıştırmak; yanlış fonksiyonların çağrılmasına, kaynak sızıntılarına ve “Ama bu sınıfı ezmiştim!” şaşkınlığına yol açabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-statik-ve-16.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-statik-ve-16.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Python Çoklu Kalıtımında MRO: Metotlar Neden Beklenmedik Yere Gidiyor?</title><link href="https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor/" rel="alternate" type="text/html" title="Python Çoklu Kalıtımında MRO: Metotlar Neden Beklenmedik Yere Gidiyor?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor</id><content type="html" xml:base="https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor/"><![CDATA[<p>Python’da çoklu kalıtım ilk bakışta oldukça masum görünür: Bir sınıf, birden fazla sınıftan özellik kazanır ve herkes mutlu olur. Ancak aynı isimli metotlar, elmas biçimli kalıtım zincirleri ve <code class="language-plaintext highlighter-rouge">super()</code> çağrıları devreye girdiğinde Python’ın hangi metodu çalıştırdığı şaşırtıcı olabilir. Bu karar rastgele verilmez; arka planda Method Resolution Order, yani MRO adı verilen kesin bir sıralama bulunur.
``</p>
<h2 id="mro-tam-olarak-nedir">MRO tam olarak nedir?</h2>

<p>MRO, bir özellik veya metot aranırken sınıfların hangi sırayla ziyaret edileceğini belirtir. Python 3 bu sırayı oluşturmak için <strong>C3 doğrusallaştırma</strong> algoritmasını kullanır. Amaç; çocuk sınıfları ebeveynlerden önce tutmak, sınıf bildirimindeki soldan sağa önceliği korumak ve kalıtım ağında tutarlı bir sıra üretmektir.</p>

<p>Bir <code class="language-plaintext highlighter-rouge">C</code> sınıfı, <code class="language-plaintext highlighter-rouge">B1, B2, ..., Bn</code> sınıflarından türetiliyorsa sıralama kabaca şöyle ifade edilir:</p>

\[L(C) = [C] + merge(L(B_1), L(B_2), \ldots, L(B_n), [B_1, B_2, \ldots, B_n])\]

<p>Buradaki <code class="language-plaintext highlighter-rouge">merge</code>, başka listelerin kuyruklarında bulunmayan uygun bir baş elemanı seçer. Bu kural, bir sınıfın kendi alt sınıfından önce aranmasını engeller.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Arama mantığı</th>
      <th>Olası sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tekli kalıtım</td>
      <td>Çocuktan ebeveyne doğru</td>
      <td>Genellikle tahmin edilebilir</td>
    </tr>
    <tr>
      <td>Basit çoklu kalıtım</td>
      <td>Soldaki ebeveyn önce</td>
      <td>Aynı adlı metot gölgelenebilir</td>
    </tr>
    <tr>
      <td>Elmas kalıtım</td>
      <td>C3 MRO sırası izlenir</td>
      <td>Ortak ata yalnızca bir kez işlenir</td>
    </tr>
    <tr>
      <td>Doğrudan sınıf çağrısı</td>
      <td>Belirtilen sınıf zorla kullanılır</td>
      <td>Zincir ve diğer sınıflar atlanabilir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/python-coklu-kalitiminda-68.svg" alt="python-coklu-kalitiminda-68" /></p>

<h2 id="beklenmedik-davranış-örneği">Beklenmedik davranış örneği</h2>

<p>Aşağıdaki örnekte iki ara sınıf aynı metodu değiştirir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Temel</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">Temel</span><span class="sh">"</span>

<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Temel</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">A -&gt; </span><span class="sh">"</span> <span class="o">+</span> <span class="nf">super</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">Temel</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">B -&gt; </span><span class="sh">"</span> <span class="o">+</span> <span class="nf">super</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">):</span>
    <span class="k">pass</span>

<span class="n">nesne</span> <span class="o">=</span> <span class="nc">C</span><span class="p">()</span>
<span class="nf">print</span><span class="p">(</span><span class="n">nesne</span><span class="p">.</span><span class="nf">mesaj</span><span class="p">())</span>
<span class="nf">print</span><span class="p">(</span><span class="n">C</span><span class="p">.</span><span class="nf">mro</span><span class="p">())</span>
</code></pre></div></div>

<p>Çıktı şu yapıdadır:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A -&gt; B -&gt; Temel
[C, A, B, Temel, object]
</code></pre></div></div>

<p>Şaşırtıcı nokta, <code class="language-plaintext highlighter-rouge">A</code> içindeki <code class="language-plaintext highlighter-rouge">super()</code> çağrısının doğrudan <code class="language-plaintext highlighter-rouge">Temel</code> sınıfına gitmemesidir. <code class="language-plaintext highlighter-rouge">super()</code>, “ebeveynimi çağır” anlamına gelmez; <strong>mevcut MRO’da benden sonraki sınıfa geç</strong> demektir. Dolayısıyla <code class="language-plaintext highlighter-rouge">C(A, B)</code> için <code class="language-plaintext highlighter-rouge">A</code> sonrasında <code class="language-plaintext highlighter-rouge">B</code> çalışır.</p>

<p>Ebeveynlerin sırasını değiştirirsek sonuç da değişir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">A</span><span class="p">):</span>
    <span class="k">pass</span>

<span class="nf">print</span><span class="p">(</span><span class="nc">D</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">())</span>
<span class="c1"># B -&gt; A -&gt; Temel
</span></code></pre></div></div>

<p>Yalnızca sınıf bildirimindeki sıra değişmesine rağmen davranış tersine dönmüştür. Özellikle mixin kullanılan büyük projelerde bu durum sessiz ve zor bulunan hatalar doğurabilir.</p>

<h2 id="super-zinciri-nasıl-güvenli-kurulur"><code class="language-plaintext highlighter-rouge">super()</code> zinciri nasıl güvenli kurulur?</h2>

<p>İşbirlikçi çoklu kalıtımda zincire katılan bütün sınıflar uyumlu davranmalıdır. Her sınıf <code class="language-plaintext highlighter-rouge">super()</code> çağırmalı, metot imzaları birbiriyle çelişmemeli ve zincir doğrudan sınıf adıyla kesilmemelidir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">KayitMixin</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Kayıt günlüğü oluşturuldu</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="nf">super</span><span class="p">().</span><span class="nf">kaydet</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">DogrulamaMixin</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">kwargs</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="sh">"</span><span class="s">ad</span><span class="sh">"</span><span class="p">):</span>
            <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">ad gerekli</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="nf">super</span><span class="p">().</span><span class="nf">kaydet</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Depo</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">return</span> <span class="sa">f</span><span class="sh">"</span><span class="s">Kaydedildi: </span><span class="si">{</span><span class="n">kwargs</span><span class="p">[</span><span class="sh">'</span><span class="s">ad</span><span class="sh">'</span><span class="p">]</span><span class="si">}</span><span class="sh">"</span>

<span class="k">class</span> <span class="nc">Servis</span><span class="p">(</span><span class="n">KayitMixin</span><span class="p">,</span> <span class="n">DogrulamaMixin</span><span class="p">,</span> <span class="n">Depo</span><span class="p">):</span>
    <span class="k">pass</span>
</code></pre></div></div>

<p>Bu tasarımda her katman yalnızca kendi görevini yapar ve kontrolü sıradaki sınıfa bırakır. <code class="language-plaintext highlighter-rouge">Servis.mro()</code> çağrısı, gerçek yürütme yolunu incelemenin en pratik yöntemidir.</p>

<h2 id="akılda-tutulması-gerekenler">Akılda tutulması gerekenler</h2>

<p>MRO’yu bir soy ağacından çok, Python’ın önceden hazırladığı bir ziyaret listesi gibi düşünün. <code class="language-plaintext highlighter-rouge">super()</code> bu listede tek adım ilerler. Beklenmedik bir sonuçla karşılaştığınızda <code class="language-plaintext highlighter-rouge">Sinif.__mro__</code> veya <code class="language-plaintext highlighter-rouge">Sinif.mro()</code> çıktısını kontrol edin; ebeveyn sırasını bilinçli belirleyin ve doğrudan <code class="language-plaintext highlighter-rouge">A.metot(self)</code> çağrılarından kaçının. Çoklu kalıtım güçlüdür, fakat MRO okunmadan kullanıldığında kod tabanına küçük bir labirent yerleştirebilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="python" /><category term="mro" /><category term="çoklu-kalıtım" /><category term="oop" /><category term="c3-doğrusallaştırma" /><category term="super" /><summary type="html"><![CDATA[Python’da çoklu kalıtım ilk bakışta oldukça masum görünür: Bir sınıf, birden fazla sınıftan özellik kazanır ve herkes mutlu olur. Ancak aynı isimli metotlar, elmas biçimli kalıtım zincirleri ve super() çağrıları devreye girdiğinde Python’ın hangi metodu çalıştırdığı şaşırtıcı olabilir. Bu karar rastgele verilmez; arka planda Method Resolution Order, yani MRO adı verilen kesin bir sıralama bulunur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/python-coklu-kalitiminda-68.png" /><media:content medium="image" url="https://program.sonsuz.us/img/python-coklu-kalitiminda-68.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotik Sinir Ağı Kontrolünde Kararlılık: Zeki Ama Garantisi Nerede?</title><link href="https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede/" rel="alternate" type="text/html" title="Robotik Sinir Ağı Kontrolünde Kararlılık: Zeki Ama Garantisi Nerede?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede/"><![CDATA[<p>Bir robot kolunun sinir ağıyla kusursuz biçimde bardak taşıdığını düşünün. Etkileyici, değil mi? Peki kol daha ağır bir bardakla, eğitilmediği bir açıyla veya gürültülü sensörlerle karşılaşırsa ne olur? Yapay sinir ağı tabanlı kontrolcüler yüksek performans gösterebilse de klasik kontrol teorisinin sevdiği türden matematiksel kararlılık garantilerini çoğu zaman beraberinde getirmez.</p>

<p>``</p>

<h2 id="kararlılık-neden-bu-kadar-önemli">Kararlılık neden bu kadar önemli?</h2>

<p>Bir dinamik sistemi genel olarak</p>

\[\dot{x}=f(x,u)\]

<p>şeklinde ifade edebiliriz. Burada $x$ sistemin durumu, $u$ ise kontrol girişidir. Kontrolcünün görevi, örneğin robotun eklem açılarını hedeflenen denge noktasına taşımaktır.</p>

<p>Klasik yaklaşımda $u=K(x)$ seçilir ve kapalı çevrim sisteminin davranışı matematiksel olarak incelenir. Lyapunov teorisi bunun en güçlü araçlarından biridir. Pozitif tanımlı bir $V(x)$ fonksiyonu için</p>

\[V(x)&gt;0, \qquad \dot{V}(x)&lt;0\]

<p>koşulları sağlanıyorsa sistemin denge noktasına doğru ilerlediği gösterilebilir. Başka bir ifadeyle enerji benzeri bir değer sürekli azalır. Robot, matematiksel bir yokuştan aşağı yuvarlanarak hedefe yaklaşır.</p>

<p>Sinir ağı kontrolcüsünde ise giriş genellikle</p>

\[u=\pi_\theta(x)\]

<p>biçimindedir. Çok katmanlı ve doğrusal olmayan $\pi_\theta$ fonksiyonu, milyonlarca parametre içerebilir. Bu nedenle tüm durum uzayında $\dot{V}(x)&lt;0$ olduğunu kanıtlamak oldukça zordur.</p>

<h2 id="klasik-ve-öğrenen-kontrolcü-karşılaştırması">Klasik ve öğrenen kontrolcü karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Klasik kontrol</th>
      <th>Sinir ağı tabanlı kontrol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Model ihtiyacı</td>
      <td>Genellikle açık model gerekir</td>
      <td>Veriden öğrenebilir</td>
    </tr>
    <tr>
      <td>Kararlılık analizi</td>
      <td>Lyapunov, kutup ve frekans yöntemleri güçlüdür</td>
      <td>Ağın karmaşıklığı analizi zorlaştırır</td>
    </tr>
    <tr>
      <td>Genelleme</td>
      <td>Tasarım bölgesiyle sınırlıdır</td>
      <td>Eğitim dışı durumlarda belirsizdir</td>
    </tr>
    <tr>
      <td>Açıklanabilirlik</td>
      <td>Görece yüksektir</td>
      <td>Çoğu zaman kara kutudur</td>
    </tr>
    <tr>
      <td>Performans</td>
      <td>Karmaşık görevlerde sınırlanabilir</td>
      <td>Yüksek boyutlu görevlerde başarılı olabilir</td>
    </tr>
  </tbody>
</table>

<p>Buradaki temel sorun sinir ağlarının mutlaka kararsız olması değildir. Sorun, eğitim başarısının kanıt anlamına gelmemesidir. Bir kontrolcünün milyonlarca simülasyonda hata yapmaması, henüz denenmemiş bir durumda güvenli kalacağını garanti etmez. Özellikle dağılım kayması, sensör arızası, model belirsizliği ve dış bozucular robotu eğitim verisinin dışına taşıyabilir.</p>

<h2 id="simülasyon-testi-neden-yeterli-değildir">Simülasyon testi neden yeterli değildir?</h2>

<p>Aşağıdaki basit Python kodu, öğrenilmiş bir kontrolcüyü farklı başlangıç durumlarında deneyerek son durum normunu ölçer:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">controller</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="c1"># Gerçekte burada eğitilmiş sinir ağı çalıştırılır.
</span>    <span class="k">return</span> <span class="o">-</span><span class="mf">1.8</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.15</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">tanh</span><span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">simulate</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">dt</span><span class="o">=</span><span class="mf">0.01</span><span class="p">,</span> <span class="n">steps</span><span class="o">=</span><span class="mi">1000</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">steps</span><span class="p">):</span>
        <span class="n">u</span> <span class="o">=</span> <span class="nf">controller</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
        <span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">dt</span> <span class="o">*</span> <span class="p">(</span><span class="o">-</span><span class="mf">0.4</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">u</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">x</span>

<span class="k">for</span> <span class="n">x0</span> <span class="ow">in</span> <span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">21</span><span class="p">):</span>
    <span class="n">final_state</span> <span class="o">=</span> <span class="nf">simulate</span><span class="p">(</span><span class="n">x0</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">x0</span><span class="p">,</span> <span class="nf">abs</span><span class="p">(</span><span class="n">final_state</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu deney faydalıdır; çünkü başarısız başlangıç bölgelerini ortaya çıkarabilir. Ancak yalnızca 21 nokta test edilir. Sürekli durum uzayında sonsuz sayıda olasılık bulunduğundan, başarılı sonuçlar biçimsel bir ispat oluşturmaz. Test güven verir, kanıt ise sınırları tanımlar.</p>

<h2 id="garantiyi-güçlendiren-yaklaşımlar">Garantiyi güçlendiren yaklaşımlar</h2>

<p>Araştırmacılar bu açığı kapatmak için birkaç yöntemi birlikte kullanıyor:</p>

<ul>
  <li><strong>Lyapunov tabanlı öğrenme:</strong> Ağ, yalnızca görev ödülünü değil, $\dot{V}(x)&lt;0$ koşulunu da dikkate alarak eğitilir.</li>
  <li><strong>Control Barrier Function:</strong> Kontrol girişleri güvenli durum kümesinde kalacak şekilde filtrelenir.</li>
  <li><strong>Hibrit mimari:</strong> Sinir ağı yüksek performanslı komut üretirken klasik kontrolcü güvenlik katmanı olarak çalışır.</li>
  <li><strong>Doğrulama araçları:</strong> Aralık analizi, erişilebilirlik analizi ve karma tamsayılı programlama ile ağın belirli bölgelerdeki çıktıları sınırlandırılır.</li>
  <li><strong>Gürbüzlük analizi:</strong> Bozucular altında durumun sınırlı kaldığını göstermek için input-to-state stability gibi kavramlardan yararlanılır.</li>
</ul>

<p>Pratikte en güvenli yaklaşım, sinir ağını tek başına direksiyona oturtmak yerine ona matematik bilen bir yardımcı pilot vermektir. Öğrenen kontrolcü çeviklik ve uyarlanabilirlik sağlarken klasik katman fiziksel sınırları, tork kısıtlarını ve güvenli çalışma bölgesini korur.</p>

<p>Sonuç olarak robotikte başarı ölçütü yalnızca görevi tamamlamak değildir. Kontrolcünün hangi koşullarda güvenli olduğunu bilmek de gerekir. Sinir ağları güçlü sürücülerdir; fakat kararlılık kanıtı olmadan emniyet kemerleri henüz tam bağlanmış sayılmaz.</p>

<p><img src="/img/robotik-sinir-agi-70.svg" alt="robotik-sinir-agi-70" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="yapay sinir ağları" /><category term="kontrol teorisi" /><category term="kararlılık" /><category term="lyapunov" /><category term="makine öğrenmesi" /><summary type="html"><![CDATA[Bir robot kolunun sinir ağıyla kusursuz biçimde bardak taşıdığını düşünün. Etkileyici, değil mi? Peki kol daha ağır bir bardakla, eğitilmediği bir açıyla veya gürültülü sensörlerle karşılaşırsa ne olur? Yapay sinir ağı tabanlı kontrolcüler yüksek performans gösterebilse de klasik kontrol teorisinin sevdiği türden matematiksel kararlılık garantilerini çoğu zaman beraberinde getirmez.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotik-sinir-agi-70.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotik-sinir-agi-70.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotlarda Sensör Kalibrasyonu Neden Zamanla Kayar?</title><link href="https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar/" rel="alternate" type="text/html" title="Robotlarda Sensör Kalibrasyonu Neden Zamanla Kayar?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar/"><![CDATA[<p><img src="/img/robotlarda-sensor-kalibrasyonu-26.svg" alt="robotlarda-sensor-kalibrasyonu-26" /></p>

<p>Bir robot fabrikadan kusursuz kalibre edilmiş biçimde çıksa bile bu durum sonsuza kadar sürmez. Kamera, LiDAR, IMU, enkoder ve GPS gibi sensörlerin ölçümleri; sıcaklık, titreşim, mekanik aşınma ve elektronik yaşlanma nedeniyle zamanla birbirinden uzaklaşır. Robot hâlâ veri topluyor gibi görünür, ancak artık dünyayı hafifçe “yamuk” algılıyordur. İşte bu yavaş bozulmaya kalibrasyon kayması, yani <strong>drift</strong> denir.</p>

<p>``</p>

<h2 id="çoklu-sensör-kalibrasyonu-nedir">Çoklu sensör kalibrasyonu nedir?</h2>

<p>Çoklu sensörlü bir sistemde yalnızca her sensörün kendi doğruluğu değil, sensörlerin birbirleriyle olan geometrik ve zamansal ilişkileri de önemlidir. Örneğin kamera ile LiDAR arasındaki dönüşüm genellikle şu katı cisim dönüşümüyle gösterilir:</p>

\[\mathbf{p}_{kamera} = \mathbf{R}\mathbf{p}_{lidar} + \mathbf{t}\]

<p>Burada $\mathbf{R}$ dönme matrisini, $\mathbf{t}$ ise öteleme vektörünü temsil eder. Sensör yuvasının bir vida kadar oynaması bile bu dış parametreleri değiştirir. Benzer şekilde kameranın odak uzaklığı veya mercek bozulması gibi iç parametreler de sıcaklık ve darbe etkisiyle sapabilir.</p>

<p>Zamansal kalibrasyon da en az geometrik kalibrasyon kadar kritiktir. Kamera görüntüsü ile IMU ölçümü arasında $\Delta t$ gecikmesi varsa hızlı hareket sırasında aynı fiziksel an karşılaştırılmaz. Açısal hız $\omega$ olduğunda yaklaşık yönelim hatası şöyle büyür:</p>

\[\Delta \theta \approx \omega \Delta t\]

<p>Robot hızlandıkça küçücük bir saat farkının büyük konum hatasına dönüşmesinin nedeni budur.</p>

<h2 id="drift-neden-oluşur">Drift neden oluşur?</h2>

<table>
  <thead>
    <tr>
      <th>Drift kaynağı</th>
      <th>Etkilenen bileşen</th>
      <th>Olası belirti</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıcaklık değişimi</td>
      <td>IMU biası, kamera odağı</td>
      <td>Konumun yavaşça sürüklenmesi</td>
    </tr>
    <tr>
      <td>Titreşim ve darbe</td>
      <td>Sensörün dış dönüşümü</td>
      <td>Nokta bulutunun görüntüyle örtüşmemesi</td>
    </tr>
    <tr>
      <td>Mekanik aşınma</td>
      <td>Enkoder, mafsal geometrisi</td>
      <td>Tekrarlanan hareketlerde farklı sonuç</td>
    </tr>
    <tr>
      <td>Saat kayması</td>
      <td>Sensör zaman damgaları</td>
      <td>Hızlı dönüşlerde çift kenarlar</td>
    </tr>
    <tr>
      <td>Elektronik yaşlanma</td>
      <td>Kazanç ve ofset</td>
      <td>Sistematik ölçüm sapması</td>
    </tr>
    <tr>
      <td>Yazılım güncellemesi</td>
      <td>Sürücü ve koordinat sistemi</td>
      <td>Güncelleme sonrası ani uyumsuzluk</td>
    </tr>
  </tbody>
</table>

<p>Drift her zaman doğrusal ilerlemez. Robot soğukken farklı, çalışma sıcaklığına ulaştığında farklı davranabilir. Bu nedenle yalnızca “ayda bir kalibre et” yaklaşımı her sistem için yeterli değildir.</p>

<h2 id="yeniden-kalibrasyon-zamanı-nasıl-anlaşılır">Yeniden kalibrasyon zamanı nasıl anlaşılır?</h2>

<p>Kalibrasyon sağlığı, sensörlerin ortak gözlemleri arasındaki <strong>residual</strong>, yani artık hata üzerinden izlenebilir. Ölçülen değer $z_i$, modelin tahmini $h_i(\mathbf{x})$ ise toplam hata:</p>

\[J(\mathbf{x}) = \sum_i \left\\vert z_i-h_i(\mathbf{x})\right\\vert _{\Sigma_i^{-1}}^2\]

<p>şeklinde tanımlanabilir. $J$ değerinin sürekli yükselmesi, sensör ilişkisinin bozulduğuna işaret eder. Ancak hareketli nesneler, yağmur veya kirli mercek de residual değerini artırabileceğinden tek ölçümle karar verilmemelidir.</p>

<p>Aşağıdaki Python örneği, hata serisinin hareketli ortalamasını izleyerek basit bir yeniden kalibrasyon uyarısı üretir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">collections</span> <span class="kn">import</span> <span class="n">deque</span>

<span class="k">class</span> <span class="nc">CalibrationMonitor</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">window</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">1.5</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">errors</span> <span class="o">=</span> <span class="nf">deque</span><span class="p">(</span><span class="n">maxlen</span><span class="o">=</span><span class="n">window</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">threshold</span> <span class="o">=</span> <span class="n">threshold</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">residual</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">residual</span><span class="p">)</span>
        <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">.</span><span class="n">maxlen</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>

        <span class="n">mean_error</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span> <span class="o">/</span> <span class="nf">len</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">mean_error</span> <span class="o">&gt;</span> <span class="n">self</span><span class="p">.</span><span class="n">threshold</span>

<span class="n">monitor</span> <span class="o">=</span> <span class="nc">CalibrationMonitor</span><span class="p">(</span><span class="n">window</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">1.5</span><span class="p">)</span>

<span class="k">for</span> <span class="n">error</span> <span class="ow">in</span> <span class="p">[</span><span class="mf">0.8</span><span class="p">]</span> <span class="o">*</span> <span class="mi">20</span> <span class="o">+</span> <span class="p">[</span><span class="mf">1.9</span><span class="p">]</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">monitor</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">error</span><span class="p">):</span>
        <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Yeniden kalibrasyon öneriliyor!</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">break</span>
</code></pre></div></div>

<p>Bu kod ani bir sıçrama yerine son 30 ölçümün ortalamasını kullanır. Gerçek sistemlerde sıcaklık, robot hızı ve titreşim seviyesi de karara eklenerek yanlış alarmlar azaltılabilir.</p>

<h2 id="takvim-mi-koşul-bazlı-bakım-mı">Takvim mi, koşul bazlı bakım mı?</h2>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Periyodik kalibrasyon</td>
      <td>Planlaması kolaydır</td>
      <td>Gereksiz bakım yapılabilir</td>
    </tr>
    <tr>
      <td>Koşul bazlı kalibrasyon</td>
      <td>Gerçek bozulmaya tepki verir</td>
      <td>İzleme altyapısı gerektirir</td>
    </tr>
    <tr>
      <td>Sürekli çevrim içi kalibrasyon</td>
      <td>Drift hareket sırasında düzeltilir</td>
      <td>Gözlemlenebilirlik ve hesaplama zordur</td>
    </tr>
    <tr>
      <td>Hibrit yaklaşım</td>
      <td>Güvenlik ile verimliliği dengeler</td>
      <td>Tasarımı daha karmaşıktır</td>
    </tr>
  </tbody>
</table>

<p>Güvenlik kritik robotlarda en sağlam çözüm genellikle hibrittir: residual değerleri sürekli izlenir, eşik aşılırsa erken bakım yapılır ve buna rağmen belirli aralıklarla doğrulama kalibrasyonu uygulanır. Ayrıca kalibrasyon parametreleri sıcaklıkla birlikte kaydedilmeli, sensör montajları işaretlenmeli ve her bakım sonrası referans veri setiyle test edilmelidir.</p>

<p>Sonuç olarak kalibrasyon tek seferlik bir kurulum adımı değil, robotun yaşam döngüsü boyunca yönetilmesi gereken bir sağlık göstergesidir. Robotun dünyayı doğru görmesini istiyorsak yalnızca sensörlerin çalışıp çalışmadığını değil, hâlâ aynı dünyaya bakıp bakmadıklarını da sorgulamalıyız.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="sensör füzyonu" /><category term="kalibrasyon" /><category term="drift" /><category term="python" /><category term="otonom sistemler" /><summary type="html"><![CDATA[Bir robot fabrikadan kusursuz kalibre edilmiş biçimde çıksa bile bu durum sonsuza kadar sürmez. Kamera, LiDAR, IMU, enkoder ve GPS gibi sensörlerin ölçümleri; sıcaklık, titreşim, mekanik aşınma ve elektronik yaşlanma nedeniyle zamanla birbirinden uzaklaşır. Robot hâlâ veri topluyor gibi görünür, ancak artık dünyayı hafifçe “yamuk” algılıyordur. İşte bu yavaş bozulmaya kalibrasyon kayması, yani drift denir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotlarda-sensor-kalibrasyonu-26.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotlarda-sensor-kalibrasyonu-26.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir</title><link href="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/" rel="alternate" type="text/html" title="Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir</id><content type="html" xml:base="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/"><![CDATA[<p>Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.</p>

<p>``</p>

<h2 id="açık-kaynak-erişilebilirliği-nasıl-artırıyor">Açık kaynak erişilebilirliği nasıl artırıyor?</h2>

<p>Açık kaynaklı donanımda devre şemaları, yazılım araçları, kütüphaneler ve örnek projeler toplulukla paylaşılır. Kullanıcı yalnızca hazır bir ürünü tüketmez; sistemin nasıl çalıştığını inceleyebilir, değiştirebilir ve yeniden üretebilir. Bu yaklaşım erişilebilirliği üç yönden güçlendirir:</p>

<ul>
  <li><strong>Ekonomik erişim:</strong> Düşük maliyetli kartlar ve uyumlu yan ürünler kullanılabilir.</li>
  <li><strong>Bilgiye erişim:</strong> Ücretsiz belgeler, videolar ve topluluk forumları öğrenme sürecini destekler.</li>
  <li><strong>Deneysel erişim:</strong> Öğrenci, hata yapmaktan korkmadan devreyi ve kodu değiştirebilir.</li>
</ul>

<p>Robotik sistemlerin temelinde algılama, karar verme ve hareket etme döngüsü bulunur. Sensör çevreden veri toplar, kontrol birimi bu veriyi işler ve aktüatörler fiziksel tepki üretir:</p>

\[Algılama \rightarrow Karar \rightarrow Hareket\]

<p>Örneğin ultrasonik sensörün gönderdiği ses dalgasının geri dönüş süresi $t$, ses hızı $v$ ve engel uzaklığı $d$ arasındaki ilişki şöyledir:</p>

\[d = \frac{v \cdot t}{2}\]

<p>İkiye bölünmesinin nedeni, ölçülen sürenin sesin engele gidişini ve geri dönüşünü birlikte içermesidir. Böyle bir formül, fizik bilgisini doğrudan çalışan bir robot üzerinde görünür hâle getirir.</p>

<h2 id="arduino-mu-raspberry-pi-mı">Arduino mu, Raspberry Pi mı?</h2>

<p>Her iki platform da robotik eğitiminde değerlidir; ancak aynı işi yapmak üzere tasarlanmamıştır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Arduino</th>
      <th>Raspberry Pi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yapı</td>
      <td>Mikrodenetleyici kartı</td>
      <td>Tek kart bilgisayar</td>
    </tr>
    <tr>
      <td>İşletim sistemi</td>
      <td>Yok</td>
      <td>Genellikle Linux</td>
    </tr>
    <tr>
      <td>Başlangıç süresi</td>
      <td>Neredeyse anlık</td>
      <td>İşletim sistemi açılışı gerekir</td>
    </tr>
    <tr>
      <td>Güç tüketimi</td>
      <td>Düşük</td>
      <td>Daha yüksek</td>
    </tr>
    <tr>
      <td>Uygun görevler</td>
      <td>Sensör, motor, gerçek zamanlı kontrol</td>
      <td>Görüntü işleme, yapay zekâ, ağ uygulamaları</td>
    </tr>
    <tr>
      <td>Başlangıç zorluğu</td>
      <td>Elektronik odaklı ve sade</td>
      <td>Yazılım olanakları geniş, yapılandırması daha ayrıntılı</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/arduino-ve-raspberry-56.svg" alt="arduino-ve-raspberry-56" /></p>

<p>Arduino, çizgi izleyen veya engelden kaçan bir robot için güçlü bir başlangıçtır. Raspberry Pi ise kamera görüntüsünden nesne tanıyan ya da web arayüzüyle yönetilen robotlarda öne çıkar. İki kart birlikte de kullanılabilir: Raspberry Pi yüksek seviyeli kararları verirken Arduino motorları zamanlamaya duyarlı biçimde kontrol edebilir.</p>

<h2 id="küçük-bir-robot-refleksi">Küçük bir robot refleksi</h2>

<p>Aşağıdaki Arduino kodu, bir dijital sensör engel algıladığında motor kontrol çıkışını durdurur. Bu örnek, algılama-karar-hareket döngüsünün en sade hâlidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">int</span> <span class="n">sensorPin</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">motorPin</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">,</span> <span class="n">INPUT</span><span class="p">);</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="n">OUTPUT</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
  <span class="kt">bool</span> <span class="n">engelVar</span> <span class="o">=</span> <span class="n">digitalRead</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">engelVar</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>    <span class="c1">// Motoru durdur</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">180</span><span class="p">);</span>  <span class="c1">// Orta-yüksek hızda ilerle</span>
  <span class="p">}</span>

  <span class="n">delay</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// Sensörü saniyede yaklaşık 50 kez kontrol et</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Kod yalnızca programlamayı değil, giriş-çıkış mantığını ve geri beslemeyi de öğretir. Öğrenci <code class="language-plaintext highlighter-rouge">180</code> değerini değiştirerek hızın davranışa etkisini gözlemleyebilir. Elbette gerçek bir motor doğrudan karta bağlanmamalı; motor sürücü devresi ve uygun güç kaynağı kullanılmalıdır.</p>

<h2 id="erişilebilirlik-yalnızca-düşük-fiyat-değildir">Erişilebilirlik yalnızca düşük fiyat değildir</h2>

<p>Ucuz kartlar tek başına eşit eğitim fırsatı oluşturmaz. İnternet erişimi, yerelleştirilmiş içerik, öğretmen eğitimi, yedek parça bulunabilirliği ve güvenli çalışma ortamı da önemlidir. Ayrıca açık kaynak projelerde belgelerin güncelliği değişebilir ve Raspberry Pi gibi kartların toplam maliyetine güç kaynağı, hafıza kartı ve çevre birimleri eklenebilir.</p>

<p>Buna rağmen bu platformların en büyük katkısı, öğrenciyi pasif kullanıcıdan üreticiye dönüştürmesidir. Bir LED’i yakmakla başlayan yolculuk; otonom araçlara, tarım robotlarına veya yapay zekâ destekli sistemlere uzanabilir. Robotik böylece ulaşılmaz bir gelecek teknolojisi değil, parçalarına ayrılıp anlaşılabilen ve yeniden tasarlanabilen bir öğrenme alanı hâline gelir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="arduino" /><category term="raspberry pi" /><category term="robotik" /><category term="açık kaynak" /><category term="stem" /><category term="elektronik" /><summary type="html"><![CDATA[Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" /><media:content medium="image" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C Dosya İşlemleri: Stream’lerle Kalıcı Veri Okuma ve Yazma</title><link href="https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma/" rel="alternate" type="text/html" title="C Dosya İşlemleri: Stream’lerle Kalıcı Veri Okuma ve Yazma" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma/"><![CDATA[<p>Bir C programı çalışırken değişkenler çoğunlukla RAM’de yaşar ve program sonlandığında sahneden sessizce çekilir. Oysa kullanıcı kayıtları, ayarlar veya ölçüm sonuçları gibi verilerin yeniden kullanılabilmesi için diske yazılması gerekir. C’nin File I/O araçları, geçici bellek ile kalıcı depolama arasında bir köprü kurar.</p>

<p>``</p>

<h2 id="stream-mantığı-nedir">Stream mantığı nedir?</h2>

<p>C, dosya ve aygıtlarla iletişimi <strong>stream</strong>, yani veri akışı soyutlaması üzerinden gerçekleştirir. Program açısından stream, sırayla okunabilen veya yazılabilen karakter ve bayt dizisidir. Bunun arkasında SSD, terminal ya da başka bir aygıt bulunabilir; temel işlemler büyük ölçüde aynı kalır.</p>

<p><code class="language-plaintext highlighter-rouge">&lt;stdio.h&gt;</code> kütüphanesindeki <code class="language-plaintext highlighter-rouge">FILE</code> yapısı bir stream’i temsil eder. Bu yapı dosyanın konumu, erişim modu, tampon bilgisi ve hata durumu gibi ayrıntıları yönetir. Genellikle yapının iç alanlarına doğrudan dokunulmaz; onun yerine <code class="language-plaintext highlighter-rouge">fopen</code>, <code class="language-plaintext highlighter-rouge">fclose</code>, <code class="language-plaintext highlighter-rouge">fprintf</code> ve <code class="language-plaintext highlighter-rouge">fread</code> gibi fonksiyonlar kullanılır.</p>

<p>Bir dosyanın toplam boyutu kabaca</p>

\[S = n \times b\]

<p>ile düşünülebilir. Burada $n$ kayıt sayısını, $b$ ise her kaydın bayt cinsinden ortalama boyutunu gösterir. Metin dosyalarında karakter kodlaması ve ayraçlar nedeniyle gerçek boyut değişebilir.</p>

<p>C programları açıldığında üç standart stream hazırdır:</p>

<table>
  <thead>
    <tr>
      <th>Stream</th>
      <th>Görevi</th>
      <th>Varsayılan aygıt</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stdin</code></td>
      <td>Veri okumak</td>
      <td>Klavye</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stdout</code></td>
      <td>Normal çıktı yazmak</td>
      <td>Terminal</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stderr</code></td>
      <td>Hata mesajı yazmak</td>
      <td>Terminal</td>
    </tr>
  </tbody>
</table>

<h2 id="dosya-açma-modları">Dosya açma modları</h2>

<p>Dosya işlemi, <code class="language-plaintext highlighter-rouge">fopen</code> ile bir stream açarak başlar. Fonksiyon başarısız olursa <code class="language-plaintext highlighter-rouge">NULL</code> döndürür; bu kontrolü atlamak, programı hata festivaline dönüştürebilir.</p>

<table>
  <thead>
    <tr>
      <th>Mod</th>
      <th>Anlamı</th>
      <th>Dosya yoksa</th>
      <th>Mevcut içerik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">r</code></td>
      <td>Okuma</td>
      <td>Hata</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">w</code></td>
      <td>Yazma</td>
      <td>Oluşturulur</td>
      <td>Silinir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">a</code></td>
      <td>Sona ekleme</td>
      <td>Oluşturulur</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">r+</code></td>
      <td>Okuma ve yazma</td>
      <td>Hata</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">w+</code></td>
      <td>Okuma ve yazma</td>
      <td>Oluşturulur</td>
      <td>Silinir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">a+</code></td>
      <td>Okuma ve sona ekleme</td>
      <td>Oluşturulur</td>
      <td>Korunur</td>
    </tr>
  </tbody>
</table>

<p>İkili dosyalarda moda <code class="language-plaintext highlighter-rouge">b</code> eklenebilir: <code class="language-plaintext highlighter-rouge">rb</code>, <code class="language-plaintext highlighter-rouge">wb</code> veya <code class="language-plaintext highlighter-rouge">ab</code> gibi.</p>

<h2 id="metin-dosyasına-yazma-ve-okuma">Metin dosyasına yazma ve okuma</h2>

<p>Aşağıdaki örnek, bir puanı dosyaya yazar ve ardından geri okur:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">FILE</span> <span class="o">*</span><span class="n">dosya</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"puan.txt"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">dosya</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"Dosya acilamadi"</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">fprintf</span><span class="p">(</span><span class="n">dosya</span><span class="p">,</span> <span class="s">"%s %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">"Ada"</span><span class="p">,</span> <span class="mi">95</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">dosya</span><span class="p">);</span>

    <span class="n">dosya</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"puan.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">dosya</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"Dosya okunamadi"</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">char</span> <span class="n">isim</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">puan</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">fscanf</span><span class="p">(</span><span class="n">dosya</span><span class="p">,</span> <span class="s">"%31s %d"</span><span class="p">,</span> <span class="n">isim</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">puan</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Ogrenci: %s, puan: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">isim</span><span class="p">,</span> <span class="n">puan</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">fclose</span><span class="p">(</span><span class="n">dosya</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">fprintf</code>, biçimlendirilmiş veriyi stream’e gönderir. <code class="language-plaintext highlighter-rouge">fscanf</code> ise veriyi belirtilen formata göre ayrıştırır. <code class="language-plaintext highlighter-rouge">%31s</code> sınırı, 32 elemanlı dizide taşmayı önlemek için en fazla 31 karakter okur. Her açılan dosyanın <code class="language-plaintext highlighter-rouge">fclose</code> ile kapatılması tamponlanmış verilerin diske aktarılmasını ve sistem kaynaklarının serbest bırakılmasını sağlar.</p>

<h2 id="metin-mi-ikili-dosya-mı">Metin mi, ikili dosya mı?</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Metin dosyası</th>
      <th>İkili dosya</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Okunabilirlik</td>
      <td>İnsan tarafından kolay okunur</td>
      <td>Özel araç gerekebilir</td>
    </tr>
    <tr>
      <td>Boyut</td>
      <td>Genellikle daha büyük</td>
      <td>Genellikle daha küçük</td>
    </tr>
    <tr>
      <td>Taşınabilirlik</td>
      <td>Yüksek</td>
      <td>Veri tiplerine bağlı</td>
    </tr>
    <tr>
      <td>Fonksiyonlar</td>
      <td><code class="language-plaintext highlighter-rouge">fprintf</code>, <code class="language-plaintext highlighter-rouge">fgets</code></td>
      <td><code class="language-plaintext highlighter-rouge">fwrite</code>, <code class="language-plaintext highlighter-rouge">fread</code></td>
    </tr>
  </tbody>
</table>

<p>İkili yazmada temel denklem aktarılan bayt miktarı için $B = adet \times sizeof(tür)$ biçimindedir. Örneğin <code class="language-plaintext highlighter-rouge">fwrite(dizi, sizeof(int), 10, dosya)</code> on tamsayıyı yazar.</p>

<p>Son olarak <code class="language-plaintext highlighter-rouge">feof</code> akış sonunu, <code class="language-plaintext highlighter-rouge">ferror</code> ise okuma veya yazma hatasını denetler. Sağlam bir File I/O kodu yalnızca mutlu senaryoyu değil; eksik dosyayı, bozuk veriyi ve başarısız yazmayı da hesaba katar. Böylece veriler program kapandığında buharlaşmak yerine diskte güvenle yaşamaya devam eder.</p>

<p><img src="/img/c-dosya-islemleri-83.svg" alt="c-dosya-islemleri-83" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c" /><category term="dosya işlemleri" /><category term="file io" /><category term="stream" /><category term="stdio" /><category term="programlama" /><summary type="html"><![CDATA[Bir C programı çalışırken değişkenler çoğunlukla RAM’de yaşar ve program sonlandığında sahneden sessizce çekilir. Oysa kullanıcı kayıtları, ayarlar veya ölçüm sonuçları gibi verilerin yeniden kullanılabilmesi için diske yazılması gerekir. C’nin File I/O araçları, geçici bellek ile kalıcı depolama arasında bir köprü kurar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-dosya-islemleri-83.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-dosya-islemleri-83.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# ile Multithreading: TPL, Task ve async/await Rehberi</title><link href="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/" rel="alternate" type="text/html" title="C# ile Multithreading: TPL, Task ve async/await Rehberi" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/"><![CDATA[<p>Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken <code class="language-plaintext highlighter-rouge">async/await</code>, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.
``</p>
<h2 id="eşzamanlılık-ve-paralellik-aynı-şey-değildir">Eşzamanlılık ve paralellik aynı şey değildir</h2>

<p>Eşzamanlılık, birden fazla işin zaman aralıkları iç içe geçecek şekilde ilerlemesidir. Paralellik ise bu işlerin gerçekten aynı anda, örneğin farklı işlemci çekirdeklerinde çalışmasıdır.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Temel amaç</th>
      <th>Uygun iş türü</th>
      <th>C# aracı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eşzamanlılık</td>
      <td>Beklerken başka işe geçmek</td>
      <td>Ağ, dosya, veritabanı</td>
      <td><code class="language-plaintext highlighter-rouge">async/await</code></td>
    </tr>
    <tr>
      <td>Paralellik</td>
      <td>Hesabı çekirdeklere dağıtmak</td>
      <td>Görüntü işleme, hesaplama</td>
      <td><code class="language-plaintext highlighter-rouge">Parallel</code>, TPL</td>
    </tr>
    <tr>
      <td>İş parçacığı</td>
      <td>Çalıştırma kaynağı sağlamak</td>
      <td>Düşük seviyeli kontrol</td>
      <td><code class="language-plaintext highlighter-rouge">Thread</code></td>
    </tr>
    <tr>
      <td>Görev</td>
      <td>Yapılacak işi temsil etmek</td>
      <td>Modern iş akışları</td>
      <td><code class="language-plaintext highlighter-rouge">Task</code></td>
    </tr>
  </tbody>
</table>

<p>Bir işin tek çekirdekte tamamlanma süresi $T_1$, $p$ çekirdekteki süresi $T_p$ ise teorik hızlanma şöyle ifade edilir:</p>

\[S_p = \frac{T_1}{T_p}\]

<p>İdeal durumda $S_p \approx p$ beklenir. Gerçekte görev oluşturma maliyeti, senkronizasyon ve paylaşılan kaynaklar nedeniyle bu değere nadiren ulaşılır.</p>

<h2 id="tpl-ile-cpu-ağırlıklı-işleri-çalıştırmak">TPL ile CPU ağırlıklı işleri çalıştırmak</h2>

<p>TPL, görevlerin uygun iş parçacıklarına dağıtılmasını <code class="language-plaintext highlighter-rouge">ThreadPool</code> üzerinden yönetir. Böylece her iş için elle <code class="language-plaintext highlighter-rouge">Thread</code> oluşturmak gerekmez.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>

<span class="kt">int</span><span class="p">[]</span> <span class="n">sayilar</span> <span class="p">=</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">8</span><span class="p">).</span><span class="nf">ToArray</span><span class="p">();</span>

<span class="n">Parallel</span><span class="p">.</span><span class="nf">ForEach</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="n">sayi</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="kt">double</span> <span class="n">sonuc</span> <span class="p">=</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span> <span class="p">*</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Pow</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="m">3</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">sayi</span><span class="p">}</span><span class="s">: </span><span class="p">{</span><span class="n">sonuc</span><span class="p">}</span><span class="s"> - Thread: </span><span class="p">{</span><span class="n">Environment</span><span class="p">.</span><span class="n">CurrentManagedThreadId</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Parallel.ForEach</code>, koleksiyondaki hesaplamaları mümkün olduğunda farklı iş parçacıklarında yürütür. Ancak çok küçük işlemleri paralelleştirmek, yönetim maliyeti yüzünden normal bir döngüden daha yavaş olabilir. Önce ölçmek, sonra paralelleştirmek altın kuraldır.</p>

<p>Bağımsız görevleri başlatıp hepsinin bitmesini beklemek için <code class="language-plaintext highlighter-rouge">Task.WhenAll</code> kullanılabilir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap1</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">1_000_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>
<span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap2</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">500_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>

<span class="kt">int</span><span class="p">[]</span> <span class="n">sonuclar</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Task</span><span class="p">.</span><span class="nf">WhenAll</span><span class="p">(</span><span class="n">hesap1</span><span class="p">,</span> <span class="n">hesap2</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Toplam: </span><span class="p">{</span><span class="n">sonuclar</span><span class="p">.</span><span class="nf">Sum</span><span class="p">()}</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Task.Run</code>, CPU ağırlıklı senkron kodu ThreadPool üzerinde çalıştırır. Buna karşılık zaten asenkron olan HTTP veya veritabanı çağrılarını ayrıca <code class="language-plaintext highlighter-rouge">Task.Run</code> içine koymak genellikle gereksizdir.</p>

<h2 id="asyncawait-ile-beklerken-kaynak-tüketmemek">async/await ile beklerken kaynak tüketmemek</h2>

<p><code class="language-plaintext highlighter-rouge">async</code>, metodun asenkron işlem içerebildiğini; <code class="language-plaintext highlighter-rouge">await</code> ise işlem tamamlanana kadar kontrolün çağırana geri verilebileceğini belirtir. Bu sırada iş parçacığının bloklanması gerekmez.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>

<span class="k">static</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span>
    <span class="kt">string</span> <span class="n">adres</span><span class="p">,</span>
    <span class="n">CancellationToken</span> <span class="n">iptal</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="nn">HttpClient</span> <span class="n">istemci</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
    <span class="kt">string</span> <span class="n">icerik</span> <span class="p">=</span> <span class="k">await</span> <span class="n">istemci</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span><span class="n">adres</span><span class="p">,</span> <span class="n">iptal</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">icerik</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">using</span> <span class="nn">CancellationTokenSource</span> <span class="n">kaynak</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
<span class="n">kaynak</span><span class="p">.</span><span class="nf">CancelAfter</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromSeconds</span><span class="p">(</span><span class="m">5</span><span class="p">));</span>

<span class="k">try</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">boyut</span> <span class="p">=</span> <span class="k">await</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span><span class="s">"https://example.com"</span><span class="p">,</span> <span class="n">kaynak</span><span class="p">.</span><span class="n">Token</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"İndirilen karakter: </span><span class="p">{</span><span class="n">boyut</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">OperationCanceledException</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"İşlem iptal edildi."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">CancellationToken</code>, uzun süren işlemin kontrollü biçimde durdurulmasını sağlar. <code class="language-plaintext highlighter-rouge">await</code> edilen görev hata üretirse istisna normal bir senkron metottaki gibi <code class="language-plaintext highlighter-rouge">try/catch</code> ile yakalanabilir.</p>

<h2 id="paylaşılan-veriler-ve-yarış-durumları">Paylaşılan veriler ve yarış durumları</h2>

<p>Birden fazla görev aynı değişkeni değiştirirse sonuç öngörülemez olabilir. Örneğin <code class="language-plaintext highlighter-rouge">sayac++</code> atomik değildir; okuma, artırma ve yazma adımlarından oluşur. Güvenli artırma için <code class="language-plaintext highlighter-rouge">Interlocked.Increment(ref sayac)</code> veya daha karmaşık kritik bölgelerde <code class="language-plaintext highlighter-rouge">lock</code> kullanılmalıdır.</p>

<p>Modern C# kodunda temel yaklaşım basittir: I/O ağırlıklı işlemlerde doğal asenkron API’leri <code class="language-plaintext highlighter-rouge">await</code> edin, CPU ağırlıklı ve bağımsız hesaplamalarda TPL kullanın, paylaşılan durumu azaltın ve performans kararlarını mutlaka ölçümlerle doğrulayın.</p>

<p><img src="/img/c-ile-multithreading-31.svg" alt="c-ile-multithreading-31" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="csharp" /><category term="multithreading" /><category term="tpl" /><category term="async" /><category term="await" /><category term="paralel-programlama" /><summary type="html"><![CDATA[Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken async/await, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak</title><link href="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/" rel="alternate" type="text/html" title="C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/"><![CDATA[<p><img src="/img/c-rtti-ve-63.svg" alt="c-rtti-ve-63" /></p>

<p>C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde <code class="language-plaintext highlighter-rouge">Karakter*</code> türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir <code class="language-plaintext highlighter-rouge">Buyucu</code> veya <code class="language-plaintext highlighter-rouge">Savasci</code> olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.
``</p>

<h2 id="rtti-neden-gereklidir">RTTI neden gereklidir?</h2>

<p>C++ değişkenlerinin çoğu tür bilgisi derleme zamanında bellidir. Ancak polimorfizm kullanıldığında statik tür ile dinamik tür birbirinden ayrılır:</p>

<ul>
  <li><strong>Statik tür:</strong> Değişkenin kaynak kodunda bildirilen türdür.</li>
  <li><strong>Dinamik tür:</strong> Çalışma anında gerçekten oluşturulmuş nesnenin türüdür.</li>
</ul>

<p>Bir <code class="language-plaintext highlighter-rouge">Karakter*</code> değişkeninin statik türü <code class="language-plaintext highlighter-rouge">Karakter*</code>, gösterdiği nesne <code class="language-plaintext highlighter-rouge">Buyucu</code> ise dinamik türü <code class="language-plaintext highlighter-rouge">Buyucu</code> olur. Bunu kabaca şu ilişkiyle gösterebiliriz:</p>

\[T_{statik} \neq T_{dinamik}\]

<p>RTTI özellikle taban sınıf üzerinden yönetilen nesnelerin alt sınıflarını ayırt etmek gerektiğinde devreye girer. Bunun çalışabilmesi için taban sınıfın <strong>polimorfik</strong> olması, yani en az bir sanal (<code class="language-plaintext highlighter-rouge">virtual</code>) fonksiyon içermesi gerekir. Genellikle sanal yıkıcı tanımlamak yeterlidir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="o">~</span><span class="n">Karakter</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Buyucu</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">buyuYap</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Ateş topu!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Sanal yıkıcı hem RTTI kullanımını mümkün kılar hem de nesne taban sınıf işaretçisi üzerinden silindiğinde doğru yıkıcının çağrılmasını sağlar.</p>

<h2 id="typeid-ile-türü-incelemek"><code class="language-plaintext highlighter-rouge">typeid</code> ile türü incelemek</h2>

<p><code class="language-plaintext highlighter-rouge">typeid</code> operatörü bir ifade veya tür hakkında <code class="language-plaintext highlighter-rouge">std::type_info</code> nesnesi döndürür. İki türün aynı olup olmadığı güvenilir biçimde karşılaştırılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;typeinfo&gt;</span><span class="cp">
</span>
<span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="k">typeid</span><span class="p">(</span><span class="o">*</span><span class="n">karakter</span><span class="p">)</span> <span class="o">==</span> <span class="k">typeid</span><span class="p">(</span><span class="n">Buyucu</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Bu karakter gerçekten bir büyücü.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">typeid(*karakter)</code> dinamik türü bulur. Buna karşılık <code class="language-plaintext highlighter-rouge">typeid(karakter)</code> işaretçinin kendi türünü, yani <code class="language-plaintext highlighter-rouge">Karakter*</code> türünü verir. <code class="language-plaintext highlighter-rouge">type_info::name()</code> da kullanılabilir; ancak döndürdüğü metnin biçimi derleyiciye bağlıdır ve program mantığı için güvenilir değildir.</p>

<h2 id="dynamic_cast-ile-güvenli-dönüşüm"><code class="language-plaintext highlighter-rouge">dynamic_cast</code> ile güvenli dönüşüm</h2>

<p><code class="language-plaintext highlighter-rouge">dynamic_cast</code>, polimorfik kalıtım hiyerarşilerinde çalışma zamanı kontrolü yapar. İşaretçi dönüşümü başarısız olursa <code class="language-plaintext highlighter-rouge">nullptr</code> döndürür:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="n">Buyucu</span><span class="o">*</span> <span class="n">buyucu</span> <span class="o">=</span> <span class="k">dynamic_cast</span><span class="o">&lt;</span><span class="n">Buyucu</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">karakter</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">buyucu</span><span class="o">-&gt;</span><span class="n">buyuYap</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Bu karakter büyü yapamaz.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

 <span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Referanslarda başarısızlık <code class="language-plaintext highlighter-rouge">nullptr</code> ile bildirilemez. Bu nedenle <code class="language-plaintext highlighter-rouge">dynamic_cast&lt;Buyucu&amp;&gt;</code> başarısız olduğunda <code class="language-plaintext highlighter-rouge">std::bad_cast</code> istisnası fırlatır.</p>

<h2 id="dönüşüm-araçlarının-karşılaştırması">Dönüşüm araçlarının karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Kontrol zamanı</th>
      <th>Başarısızlık davranışı</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dynamic_cast</code></td>
      <td>Çalışma zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">nullptr</code> veya <code class="language-plaintext highlighter-rouge">std::bad_cast</code></td>
      <td>Güvenli aşağı dönüşüm</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">static_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Otomatik güvenlik kontrolü yok</td>
      <td>Bilinen ve mantıksal dönüşümler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const_cast</code></td>
      <td>Derleme zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">const</code> niteliğini değiştirir</td>
      <td>Eski API uyumluluğu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reinterpret_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Bit düzeyinde riskli yorumlama</td>
      <td>Düşük seviyeli sistem kodu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">typeid</code></td>
      <td>Çalışma zamanı</td>
      <td>Tür bilgisi döndürür</td>
      <td>Gerçek türü karşılaştırma</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">static_cast</code> ile aşağı dönüşüm yapılabilir, fakat nesne hedef türde değilse davranış tanımsız olabilir. Başka bir deyişle hız uğruna emniyet kemerini çıkarmış olursunuz.</p>

<h2 id="tasarım-açısından-son-notlar">Tasarım açısından son notlar</h2>

<p>RTTI kullanışlıdır ancak her nesnenin türünü sürekli sorgulamak tasarım kokusuna dönüşebilir. Çoğu durumda sanal fonksiyonlar daha temiz bir çözüm sunar: nesneye “Sen büyücü müsün?” diye sormak yerine doğrudan <code class="language-plaintext highlighter-rouge">eylemYap()</code> çağrısı yapılabilir.</p>

<p>Yine de eklenti sistemleri, nesne editörleri ve heterojen koleksiyonlar gibi alanlarda RTTI oldukça değerlidir. Kural basittir: Tür gerçekten belirsizse <code class="language-plaintext highlighter-rouge">dynamic_cast</code>, davranış polimorfik biçimde ifade edilebiliyorsa sanal fonksiyon kullanın. Böylece C++ nesneleri maskelerini çıkarsa bile programınız şaşırmaz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="rtti" /><category term="dynamic-cast" /><category term="typeid" /><category term="tür-dönüşümü" /><category term="nesne-yönelimli-programlama" /><summary type="html"><![CDATA[C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde Karakter* türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir Buyucu veya Savasci olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Sanal Fonksiyonlar ve Çok Biçimlilik: Tek Arayüz, Farklı Davranışlar</title><link href="https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar/" rel="alternate" type="text/html" title="C++ Sanal Fonksiyonlar ve Çok Biçimlilik: Tek Arayüz, Farklı Davranışlar" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar/"><![CDATA[<p>Bir oyun geliştirdiğimizi ve ekranda savaşçı, büyücü, okçu gibi farklı karakterlerin bulunduğunu düşünelim. Her karakter saldırır, ancak saldırma biçimleri birbirinden farklıdır. C++ çok biçimliliği, bu nesneleri tek bir ortak arayüz üzerinden yönetirken doğru davranışın çalışma zamanında seçilmesini sağlar. Böylece uzun <code class="language-plaintext highlighter-rouge">if-else</code> zincirleri yerine genişletilebilir ve bakımı kolay bir tasarım elde ederiz.</p>

<p><img src="/img/c-sanal-fonksiyonlar-84.svg" alt="c-sanal-fonksiyonlar-84" /></p>

<p>``</p>

<h2 id="çok-biçimlilik-nedir">Çok biçimlilik nedir?</h2>

<p>Polymorphism, kelime anlamıyla <strong>çok biçimlilik</strong> demektir. Nesne yönelimli programlamada aynı fonksiyon çağrısının nesnenin gerçek tipine göre farklı sonuç üretmesini ifade eder. C++ içerisinde bunun iki temel çeşidi vardır:</p>

<table>
  <thead>
    <tr>
      <th>Tür</th>
      <th>Seçim zamanı</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Statik çok biçimlilik</td>
      <td>Derleme zamanı</td>
      <td>Fonksiyon aşırı yükleme, şablonlar</td>
    </tr>
    <tr>
      <td>Dinamik çok biçimlilik</td>
      <td>Çalışma zamanı</td>
      <td>Sanal fonksiyonlar ve kalıtım</td>
    </tr>
  </tbody>
</table>

<p>Dinamik çok biçimlilik için genellikle üç bileşen gerekir: bir temel sınıf, bu sınıftan türeyen sınıflar ve <code class="language-plaintext highlighter-rouge">virtual</code> olarak tanımlanmış bir üye fonksiyon.</p>

<p>Matematiksel olarak ortak bir arayüzü $I$, farklı nesne tiplerini ise $T_1, T_2, \ldots, T_n$ ile gösterelim. Aynı işlem $f$, nesnenin dinamik tipine göre farklı uygulanır:</p>

\[f(I) \rightarrow f_{T_i}(T_i)\]

<p>Yani kod <code class="language-plaintext highlighter-rouge">f</code> işlemini ortak arayüz üzerinden ister; hangi özel uygulamanın çalışacağına program çalışma zamanında karar verir.</p>

<h2 id="sanal-fonksiyon-nasıl-çalışır">Sanal fonksiyon nasıl çalışır?</h2>

<p>Aşağıdaki örnekte bütün karakterler <code class="language-plaintext highlighter-rouge">saldir()</code> arayüzünü sunar, fakat her biri kendine özgü davranır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">saldir</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Karakter saldırdı.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">virtual</span> <span class="o">~</span><span class="n">Karakter</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Savasci</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">saldir</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Savaşçı kılıcını savurdu!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Buyucu</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">saldir</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Büyücü ateş topu gönderdi!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">virtual</code> anahtar sözcüğü, çağrılacak fonksiyonun nesnenin gerçek tipine bakılarak seçilmesini sağlar. <code class="language-plaintext highlighter-rouge">override</code> ise türetilmiş sınıftaki fonksiyonun gerçekten bir sanal fonksiyonu ezdiğini derleyiciye doğrulatır. İmza yanlış yazılırsa derleyici hata verir; bu nedenle <code class="language-plaintext highlighter-rouge">override</code> kullanmak iyi bir güvenlik kemeridir.</p>

<p>Derleyiciler bu mekanizmayı çoğunlukla <strong>vtable</strong> adlı sanal fonksiyon tablosu ve nesnede tutulan gizli bir <strong>vptr</strong> işaretçisiyle gerçekleştirir. C++ standardı bu yöntemi zorunlu kılmaz, fakat yaygın uygulama budur. Sanal çağrının küçük bir dolaylı erişim maliyeti vardır; buna karşılık sağladığı esneklik çoğu uygulamada çok daha değerlidir.</p>

<h2 id="nesneleri-ortak-koleksiyonda-yönetmek">Nesneleri ortak koleksiyonda yönetmek</h2>

<p>Akıllı işaretçiler sayesinde farklı karakterleri aynı koleksiyonda güvenli biçimde saklayabiliriz:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Karakter</span><span class="o">&gt;&gt;</span> <span class="n">takim</span><span class="p">;</span>

    <span class="n">takim</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Savasci</span><span class="o">&gt;</span><span class="p">());</span>
    <span class="n">takim</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Buyucu</span><span class="o">&gt;</span><span class="p">());</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">karakter</span> <span class="o">:</span> <span class="n">takim</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">karakter</span><span class="o">-&gt;</span><span class="n">saldir</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Döngü yalnızca <code class="language-plaintext highlighter-rouge">Karakter</code> arayüzünü bilir. Buna rağmen ilk nesne kılıç kullanır, ikincisi ateş topu fırlatır. İşte dinamik çok biçimliliğin küçük ama etkileyici sihri budur.</p>

<h2 id="kritik-ayrıntılar">Kritik ayrıntılar</h2>

<p>Temel sınıf üzerinden silme yapılacaksa yıkıcı mutlaka sanal olmalıdır. Aksi hâlde türetilmiş sınıfın yıkıcısı çağrılmayabilir ve kaynak sızıntıları oluşabilir. Bu nedenle <code class="language-plaintext highlighter-rouge">virtual ~Karakter() = default;</code> önemli bir satırdır.</p>

<p>Nesneleri değer olarak kopyalamak da <strong>object slicing</strong> problemine yol açar:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Savasci</span> <span class="n">savasci</span><span class="p">;</span>
<span class="n">Karakter</span> <span class="n">kopya</span> <span class="o">=</span> <span class="n">savasci</span><span class="p">;</span> <span class="c1">// Savasci kısmı kesilir</span>
<span class="n">kopya</span><span class="p">.</span><span class="n">saldir</span><span class="p">();</span>           <span class="c1">// Temel sınıf davranışı çalışır</span>
</code></pre></div></div>

<p>Dinamik davranışı korumak için temel sınıf referansı, işaretçisi veya <code class="language-plaintext highlighter-rouge">std::unique_ptr</code> gibi akıllı işaretçiler kullanılmalıdır.</p>

<p>Sonuç olarak sanal fonksiyonlar, kodu somut sınıflara değil ortak sözleşmelere bağlar. Yeni bir <code class="language-plaintext highlighter-rouge">Okcu</code> sınıfı eklediğimizde mevcut döngüyü değiştirmemiz gerekmez. Böylece C++ programı hem yeni karakterlere hem de gelecekte gelecek sürpriz gereksinimlere hazırlıklı olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="polymorphism" /><category term="sanal fonksiyonlar" /><category term="nesne yönelimli programlama" /><category term="kalıtım" /><category term="oop" /><summary type="html"><![CDATA[Bir oyun geliştirdiğimizi ve ekranda savaşçı, büyücü, okçu gibi farklı karakterlerin bulunduğunu düşünelim. Her karakter saldırır, ancak saldırma biçimleri birbirinden farklıdır. C++ çok biçimliliği, bu nesneleri tek bir ortak arayüz üzerinden yönetirken doğru davranışın çalışma zamanında seçilmesini sağlar. Böylece uzun if-else zincirleri yerine genişletilebilir ve bakımı kolay bir tasarım elde ederiz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-sanal-fonksiyonlar-84.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-sanal-fonksiyonlar-84.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>