top of page

C++ Dilinde function try block / Function Try Block ile Ctor Exception Yönetimi: Kurallar, Tuzaklar, Örnekler

  • Writer: Yusuf Hançar
    Yusuf Hançar
  • Dec 29, 2025
  • 4 min read

  1. Problem: Constructor gövdesindeki try-catch, member init exception’ını yakalayamaz


class Member {
public :
    Member();
    Member(int);
};

class Data {
public :
    Data() : mx(1) {}

private :
    Member mx;
};

int main() {}

/*******************************************
AÇIKLAMA :
Data() kurucu işlevi(constructor) çalışırken önce mx(1) oluşturulur. Eğer Member(int) belirli koşulda exception throw ederse “ben Data() gövdesinde try-catch ile yakalarım” düşüncesi gelir.
Ama constructoror gövdesi ({ ... }) member initializer’lar tamamlandıktan sonra çalışır. Yani exception member initializer aşamasında fırlarsa, ctor gövdesine hiç girilmez.

Bu yüzden: “exception Data sınıfının constructor'ı içerisinde bir try-catch bloğu ile yakalanabilir mi?” → HAYIR.
------------------------------------------------------------------
CEVAP :
Data constructor gövdesindeki try-catch ile tutulamaz (catch’e hiç gelmez). Exception dışarı propagete olur; eğer dışarıda da yakalanmazsa std::terminate().
*******************************************/

  1. Yanlış Deneme: constructor gövdesine try-catch koymak (çalışmaz)


class Member {
public :
    Member();
    Member(int x)
    {
        if (x > 10)
        {
            throw std::runtime_error{ "exception from Member ctor\n" };
        }
    }
};

class Data {
public :
    Data(int val) : mx(val)
    {
        try
        {
        }
        catch(const std::exception& ex)
        {
            std::cerr << "exception caught : " << ex.what() << "\n";
        }
    }

private :
    Member mx;
};

int main()
{
    Data d(15);
}

/*******************************************
AÇIKLAMA :
Data(int val) çağrılınca önce mx(val) inşa edilir. val=15 → Member(int) exception fırlatır.
Fakat bu exception constructor gövdesinden önce oluştuğu için try { } catch { } bloğuna hiç girilmez.

Dışarıda (main’de) de catch yoksa → exception yakalanamaz → std::terminate() çağrılır.
std::terminate() default terminate handler ile tipik olarak programı sonlandırır (çoğu sistemde abort() ile biter).
İstenirse std::set_terminate() ile terminate davranışını özelleştirilebilir.
------------------------------------------------------------------
CEVAP :
Exception constructor içinde yakalanamaz. (main’de de catch olmadığı için) program std::terminate() ile biter.
*******************************************/

  1. Çözüm: Function Try Block (Constructor için “tek doğru yer”)

class Member {
public :
    Member();

    Member(int val)
    {
        if (val > 10)
        {
            throw std::runtime_error{ "exception from Member ctor\n" };
        }
    }
};

class Data {
public :
    Data(int val) try : mx(val)
    {
    }
    catch(const std::exception& ex)
    {
        std::cerr << "exception caught : " << ex.what() << "\n";
    }

private :
    Member mx;
};

int main()
{
    Data d(15);
}
/*****************************   
AÇIKLAMA : 
1. Buradaki kritik fark şu:

-> try ctor’un tamamını kapsıyor: hem member initializer list (: mx(val)) hem de ctor gövdesi.
-> Dolayısıyla mx(val) sırasında fırlayan exception catch tarafından yakalanabilir.

2. Ama burada ikinci kritik kural devreye girer:

-> Constructor function try block catch’i biterken exception rethrow edilmek zorundadır.

-> Sen catch içinde throw; yazmasan bile, derleyici ctor için sanki throw; varmış gibi davranır (yani exception dışarı yeniden fırlatılır).

-> Çünkü ctor başarısız olduysa, obje oluşturulamaz. Obje oluşmadığı için Data d(15); tamamlanamaz; d için destructor da çalışmaz (zaten inşa yok).

Main’de yakalayan yok → rethrow edilen exception yine yakalanmaz → terminate.
-------------------------------
CEVAP : 
exception caught : exception from Member ctor

terminate called after throwing an instance of 'std::runtime_error'
  what():  exception from Member ctor
*****************************/

  1. Aynı örnek ama main’de yakala: propagasyon net görünür

class Member {
public :
    Member();
    Member(int x)
    {
        if (x > 10)
        {
            throw std::runtime_error{ "exception from Member ctor\n" };
        }
    }
};

class Data {
public :
    Data(int val) try : mx(val)
    {
    }
    catch(const std::exception& ex)
    {
        std::cerr << "exception caught : " << ex.what() << "\n";
    }

private :
    Member mx;
};

int main()
{
    try 
    {
        Data d(15);
    }
    catch(const std::exception& ex)
    {
        std::cerr << "in main exception caught : " << ex.what() << "\n";
    }
}
/*****************************   
AÇIKLAMA : 
Data(int) function try block exception’ı yakalar, mesajı basar, sonra ctor tamamlanamadığı için exception rethrow edilir.
Bu sefer main’deki catch rethrow’u yakalar ve program kontrollü biçimde devam eder/sonlanır.
*****************************   
CEVAP : 
exception caught : exception from Member ctor
in main exception caught : exception from Member ctor
*****************************/

  1. “constructor parametresi içinde oluşan exception” function try block ile yakalanır mı?


5.1. Senaryo (Hayır)

class Error{
public :
    ///...
};

class Data {
public :
    Data(Error) {
    }
};
/*****************************   
AÇIKLAMA : 
Burada kritik detay: Data(Error) çağrılmadan önce, argüman olarak geçilen Error nesnesi çağrı noktasında oluşturulur.

Data d(Error{});

Bu durumda Error{} ctor’ı exception fırlatırsa, daha Data ctor’unun içine girilmeden (hatta function try block bile başlamadan) exception fırlamış olur.

Function try block, fonksiyon gövdesi + ctor init-list kapsamındadır.
Ama parametre/argüman oluşturma aşaması call site tarafındadır → yakalanamaz.
*****************************   
CEVAP : 
Hayır, Error argümanının oluşturulması sırasında fırlayan exception Data ctor’undaki function try block ile yakalanamaz. Ancak çağıran tarafta (main gibi) yakalanabilir.
*****************************/

  1. Function try block’ta parametre görünürlüğü (val visible)


class Data {
public :
    Data(int val) try : mx(val)
    {
    }
    catch(const std::exception& ex)
    {
        // auto x = val;  // parametre değişkeni burda visible olur.
        std::cerr << "exception caught : " << ex.what() << "\n";
    }

private :
    Member mx;
};
/*****************************   
AÇIKLAMA : 
Function try block’ta catch kısmı, aynı fonksiyonun parçası sayılır. Bu yüzden parametreler catch içinde görünür.
Bu pratikte “log bas, parametreyi yaz, telemetry ekle” gibi işlerde çok kullanışlıdır.
*****************************   
CEVAP : 
val catch içinde visible.
*****************************/

  1. Function try block sadece constructor değil: her fonksiyonda var (ama pratikte en çok constructor)


  • function try block herhangi bir fonksiyon için kullanılabilir. Ancak pratikte ctor dışında çok kritik değildir.


7.1. Örnek: catch içinde return ile toparlamak

int foo(int x)
try {
    if (x > 10)
    {
        throw std::runtime_error{ "error\n" };
    }
}
catch (const std::exception& ex)
{
    std::cerr << "exception caught : " << ex.what() << "\n";

    // burda return statement kullanabiliriz.
    return x + 5;
}
/*****************************   
AÇIKLAMA : 
Bu, “fonksiyon gövdesini komple try-catch içine almak” gibi davranır ama daha kompakt bir yazımdır:
-> try bloğu fonksiyonun body’si gibidir
-> exception olursa catch’e düşer
-> catch içinde return ile “fallback” davranışı verebilirsin

Not: Normal body içinde try { ... } catch { ... } de yazılabilir; burada fark daha çok sözdizimsel ve bazı scope detaylarında ortaya çıkar.
*****************************   
CEVAP : 
-> x <= 10 → exception yok → fonksiyon normal akar (ama örnekte return yoksa UB/derleme uyarısı olabilir; pratikte return x; gibi bir dönüş eklenir).

-> x > 10 → catch’e girer, "exception caught : error" basar, x + 5 döner.
*****************************/
  1. Tuzak: try bloğunda tanımlanan local değişken catch’te görünmez


int foo(int x)
try {
    int val{ 10 };    

    if (x > 10)
    {
        throw std::runtime_error{ "error\n" };
    }
}
catch (const std::exception& ex)
{
    std::cerr << "exception caught : " << ex.what() << "\n";

    return x + val;
}
/*****************************   
AÇIKLAMA : 
val değişkeni try { ... } bloğunun scope’undadır. catch ayrı bir scope olduğu için val burada visible değildir.
Yani return x + val; derleme hatasıdır.

Bunu çözmek için:
-> val’i try öncesinde daha dış scope’a alırsın, veya
-> catch içinde ihtiyaç varsa yeniden tanımlarsın, veya
-> exception stratejisini değiştirirsin.
*****************************   
CEVAP : Derleme hatası: val catch bloğunda tanımsız / görünmez.
*****************************/

 
 
 

Comments


bottom of page