BG MVC Model View Controller eğitim serisi yayında...

Ana sayfa > Programlama > C++ Programlama > Hata kontrolü (Exception handling)

Hata kontrolü (Exception handling)

C++'da Hata kontrolü (Exception handling) sistemi ile çalışma zamanı hatalarını düzenli bir şekilde yönetmemizi sağlar. Program çalışırken bir hata ile karşılaştığında, otomatik olarak bir hata kontrol kod bloğunu devreye sokar. Hata kontrol kodlarının bir kısmı sistem tarafından otomatik olarak sağlanmasıdır.

Hata kontrolü hakkında

Hata kontrolünde try, catch ve throw anahtar kelimeleri kullanılmaktadır. Hata kontrolü için izlemek istediğimiz program kodları bir try bloğunda yer alır. Try bloğu içinde bir hata meydana gelirse, throw anahtar kelimesi ile veri türüne bağlı olarak tanımlanan bir catch kod bloğunda işlem yapılmak üzere gönderilir. Catch anahtar kelimesi hatayı alır ve gerekli işlemleri yapar.

Try ve catch bloğunun tanımlanmasında, farklı veri türlerinin her biri için bir catch kod bloğu olmak üzere veya tüm veri türleri için tek bir catch bloğu olmak üzere iki farklı yöntem kullanılabilir. İlk yöntemde, try kod bloğu içinde karşılaşılan hata kodu veri türüne uygun olarak farklı bir catch kod bloğu seçilir. İkinci yöntemde ise, hata kodunun veri türü ne olursa olsun hata kodu aynı catch bloğuna gönderilir. Ancak, bu durumda gönderilen hata kodu catch bloğu içinde kullanılamaz.

Throw anahtar kelimesi kullanımının genel yapısı aşağıda gösterilmektedir:

throw hata-kodu;

Throw anahtar kelimesi, belirli bir veri türünden olan hata-kodu ile gösterilen hatayı oluşturur. Eğer bu hata koduna işlem yapılması gerekirse, hata kodunun veri türüne uygun olarak seçilen catch kod bloğunda doğrudan kod satırı veya fonksiyon çağrısı ile işlem yapılır.

Hata kodunun veri türüne işlem yapacak herhangi bir catch bloğu tanımlanmamış ise, program anormal bir şekilde sonlandırılabilir. Hata koduna herhangi bir işlem yapılmadığından, standart kütüphane fonksiyonu olan terminate() fonksiyonu devre girer ve abort() fonksiyonunu çağırır.

Catch bloğunun farklı veri türleri ayrı ayrı tanımlanması

Try ve catch bloğu bildiriminde, try bloğunda throw anahtar kelimesi ile gönderilecek her bir veri türü için ayrı bir catch kod bloğu tanımladığımızda kullanılacak olan genel yapı aşağıda gösterilmektedir.

try {
  // try kod bloğu
  throw hata-kodu // hata-kodu -> parametre
}
catch (veri-türü1 parametre) {
  // catch kod bloğu
}
catch (veri-türü2 parametre) {
  // catch kod bloğu
}
catch (veri-türü3 parametre) {
  // catch kod bloğu
}
.
.
.
catch (veri-türüN parametre) {
// catch kod bloğu
}

Bu yöntemle yapılan tanımlamaada, bir try catch bloğunda birden fazla catch bloğu yer alabilir. Try kod bloğu içinde throw anahtar kelimesi ile bir hata kodu gönderildiğinde, hata kodunun veri türüne karşılık gelen catch anahtar kelimesinin bulunduğu kod bloğu tarafından işlem yapılır.

Bir hata alındığında, hata kodu tanımlandığı veri tüürne bağlı olarak, catch bloğu başında tanımlanan parametreye aktarılacaktır. Try kod bloğu içinde herhangi bir hata ile karşılaşılmadığı takdirde, catch kod bloklarından hiçbiri devreye girmez.

Try ve catch bloğunun main() fonksiyonu içinde tanımlanması

Şimdi, her bir veri türü için ayrı bir catch kod bloğu tanımlanan try ve catch bloğunun hata kontrol sisteminde çalışmasını bir örnek üzerinde incelemeye çalışalım:


#include<iostream>

using namespace std;

int main(void)
{
  int id;

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  try {
    if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
    }
    else {
      throw id;
    }
  }
  catch (int idc) {
    cout << endl << "Girdiğiniz sayı 1-100 arasında değildir!" << endl;
    cout << "Girdiğiniz sayı: " << idc;
  }

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımız zaman, 21 sayısını girip ENTER tuşuna bastığımızda, aşağıdaki ifadeleri ekrana yazar:

1-100 arasında bir sayı giriniz: 21
Girdiğiniz sayı 1-100 arasındadır!

125 sayısını girip ENTER tuşuna bastığımızda ise, aşağıdaki ifadeleri ekrana yazar:

1-100 arasında bir sayı giriniz: 125
Girdiğiniz sayı 1-100 arasında değildir!
Girdiğiniz sayı: 125

Program, önce kullanıcıdan 1-100 arasında bir sayı girmesini ister. Sonra, try kod bloğunun içinde, sayının 1-100 arasında olup olmadığını kontrol eder. Eğer girilen değer belirtilen aralıkta ise, "Girdiğiniz sayı 1-100 arasındadır!" ifadesini ekrana yazar ve catch kod bloğuna giriş yapılmadan programın çalışması sona erer. Eğer girilen değer belirtilen aralıkta değil ise, throw anahtar kelimesi ile girilen değer kullanılarak int değer için oluşturulan catch kod bloğu çağrılır. Kod bloğu içinde, "Girdiğiniz sayı 1-100 arasında değildir!" ifadesini ve girilen değeri ekrana yazar ve programın çalışması sona erer.

Try kod bloğu satırlarının bir fonksiyon içinde tanımlanması

Şimdi, yukarıdaki programın yaptığı işlemin aynısını gerçekleştiren, try kod bloğu içindeki işlem satırlarını tek bir fonksiyonla gerçekleştiren, bir örneği incelemeye çalışalım:


#include<iostream>

using namespace std;

void deger_kontrol(int id)
{
  if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
  }
  else {
      throw id;
  }
}

int main(void)
{
  int id;

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  try {
    deger_kontrol(id);
  }
  catch (int idc) {
    cout << endl << "Girdiğiniz sayı 1-100 arasında değildir!" << endl;
    cout << "Girdiğiniz sayı: " << idc;
  }

  return 0;
}

Yukarıdaki program programın yaptığı işlemin aynısını gerçekleştirir. Tek fark, try kod bloğu içindeki işlem satırlarının tek bir fonksiyon içinde yer almasıdır.

Try ve catch bloğunun komple bir fonksiyon içinde tanımlanması

Şimdi, aynı programı, try catch bloğunun tamamını bir fonksiyon içinde tanımlayarak, yeniden incelemeye çalışalım:


#include<iostream>

using namespace std;

void deger_kontrol(int id)
{
  try {
    if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
    }
    else {
      throw id;
    }
  }
  catch (int idc) {
    cout << endl << "Girdiğiniz sayı 1-100 arasında değildir!" << endl;
    cout << "Girdiğiniz sayı: " << idc;
  }
}

int main(void)
{
  int id;

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  deger_kontrol(id);

  return 0;
}

Yukarıdaki program programın yaptığı işlemin aynısını gerçekleştirir. Tek fark, try catch kod bloğunun tamamının tek bir fonksiyon içinde yer almasıdır.

Try ve catch bloğunda birden fazla veri türü için catch bloğu tanımlama

Şimdi, try catch yapısında birden fazla veri türü için bildirimi yapılan catch kod bloğunun yer aldığı bir örneği incelemeye çalışalım:


#include<iostream>

using namespace std;

void deger_kontrol(int id)
{
  try {
    switch(id) {
      case 0: throw 21;
      case 1: throw 21.75f;
      case 2: throw 'a';
      case 3: throw "Hata kontrolü";
    }
  }
  catch (int idc) {
    cout << "int değer hatası: " << idc << endl;
  }
  catch (float fd) {
    cout << "float değer hatası: " << fd << endl;
  }
  catch (char cd) {
    cout << "char değer hatası: " << cd << endl;
  }
  catch (const char *cstr) {
    cout << "Karakter dizisi hatası: " << cstr << endl;
  }
}

int main(void)
{
  deger_kontrol(0);
  deger_kontrol(1);
  deger_kontrol(2);
  deger_kontrol(3);

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımız zaman, 21 sayısını girip ENTER tuşuna bastığımızda, aşağıdaki ifadeleri ekrana yazar:

int değer hatası: 21
float değer hatası: 21.75
char değer hatası: a
Karakter dizisi hatası: Hata kontrolü

Program, try catch yapısının tamamının içinde yer aldığı deger_kontrol() adlı bir fonksiyon tanımlar. Bu fonksiyondaki try kod bloğunun içinde fonksiyonun aldığı int parametre değerine göre int, float, char ve karakter dizisi verileri için ayrı ayrı birer catch kod bloğu tanımlar. Bu fonksiyona her veri türü için sırasıyla çağrı yaparak ilgili catch kod bloklarının devreye girmesini sağlar.

Try ve catch bloğunda veri türü olarak sınıfları kullanma

Try ve catch yapısında throw anahtar kelimesi ile kullanılan hata kodları sınıf olarak ta tanımlanabilir. Sınıf türünden tanımlanan hata kodları hata ile bilgileri depolamaya yarayan bir nesne oluşturduğundan fayda sağlar.

Şimdi, try catch yapısında sınıf veri türünün kullanılmasını bir örnek incelemeye çalışalım:


#include <iostream>
#include <string>

using namespace std;

class sinifhata {
  public:
    string cdizi, chata;
    int id;
    sinifhata() { cdizi = ""; chata = ""; id = 0; }
    sinifhata(string cdizig, string chatag, int idg) {
      cdizi = cdizig;
      chata = chatag;
      id = idg;
    }
};

void deger_kontrol(int id)
{
  try {
    if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
    }
    else {
      if (id<1) throw sinifhata("Değer giriş hatası!", "Değer 1'den küçük!", id);
      else throw sinifhata("Değer giriş hatası!", "Değer 100'den büyük!", id);
    }
  }
  catch (sinifhata sin) {
    cout << endl << sin.cdizi << endl;
    cout << sin.chata << endl;
    cout << "Girilen değer: " << sin.id << endl;
  }
}

int main(void)
{
  int id;

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  deger_kontrol(id);

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımız zaman, 21 sayısını girip ENTER tuşuna bastığımızda, aşağıdaki ifadeleri ekrana yazar:

1-100 arasında bir sayı giriniz: 21
Girdiğiniz sayı 1-100 arasındadır!

121 sayısını girip ENTER tuşuna bastığımızda ise, aşağıdaki ifadeleri ekrana yazar:

1-100 arasında bir sayı giriniz: 121
Değer giriş hatası!
Değer 100'den büyük!
Girilen değer: 121

0 sayısını girip ENTER tuşuna bastığımızda ise, aşağıdaki ifadeleri ekrana yazar:

1-100 arasında bir sayı giriniz: 0
Değer giriş hatası!
Değer 1'den küçük!
Girilen değer: 0

Program, sinifhata adında bir sınıf bildirimi yapar. Bu sınıfın içinde cdizi ve chata adlı iki karakter dizisi, bir adet id adlı int değişken ve parametreli ve parametresiz olmak üzere iki adet constructor fonksiyonu tanımlar. Kullanıcıdan 1-100 arasında bir sayı girmesini ister. Sonra, try ve catch yapısının yer aldığı deger_kontrol() fonksiyonunu, girilen değeri parametre olarak geçirerek, çağırır. Try kod bloğunun içinde, sayının 1-100 arasında olup olmadığını kontrol eder. Eğer girilen değer belirtilen aralıkta ise, "Girdiğiniz sayı 1-100 arasındadır!" ifadesini ekrana yazar ve catch kod bloğuna giriş yapılmadan programın çalışması sona erer. Eğer girilen değer 1'den küçük ise, throw anahtar kelimesi ile, sinifana sınıfından oluşturduğu nesneye iki karakter dizisi ve girilen değeri constructor fonksiyonu yoluyla geçirerir. Geçirilen değerler constructor fonksiyonu içinde, oluşturulan sınıf kopyasındaki iki karakter dizisi ve int değere aktarılır. Sınıf veri türü için oluşturulan catch kod bloğu çağrılır. Kod bloğu içinde, sınıf kopyası içindeki karakter dizileri ve int değer ekrana yazılır. Girilen değer 100'den büyük olduğunda ise, sadece ikinci karakter dizisi farklı olarak aynı işlemler yapılır.

Tüm veri türleri için tek bir catch kod bloğu tanımlanması

Try ve catch yapısında tüm veri türleri için tek bir catch kod bloğu tanımlayarak, throw anahtar kelimesi ile kullanılan her veri türündeki hata kodlarına aynı catch kob bloğu içinde işlem yapabiliriz.

Şimdi, tüm veri türleri için tek bir catch kod bloğu tanımlanmasını bir örnek incelemeye çalışalım:


#include<iostream>

using namespace std;

template <typename t> void deger_kontrol(t x)
{
  try {
    throw x;
  }
  catch (...) {
    cout << "Hatalı değer: " << x << endl;
  }
}

int main(void)
{
  deger_kontrol(21);
  deger_kontrol(47.52f);
  deger_kontrol('a');
  deger_kontrol("Hata kontrolü");

  return 0;
}

Yukarıdaki programı derleyip çalıştırdığımız zaman, 21 sayısını girip ENTER tuşuna bastığımızda, aşağıdaki ifadeleri ekrana yazar:

Hatalı değer: 21
Hatalı değer: 47.52
Hatalı değer: a
Hatalı değer: Hata kontrolü

Program, try catch yapısının tamamının içinde yer aldığı deger_kontrol() adlı bir şablon fonksiyon tanımlar. Bu fonksiyondaki try kod bloğunun içinde fonksiyonun aldığı parametre veri türü ne olursa olsun, tüm değerlere işlem yapabilecek tek bir catch kod bloğu tanımlar. Bu fonksiyona her veri türü için sırasıyla çağrı yaparak catch kod bloğunun devreye girmesini sağlar.

Bir fonksiyonda sadece belirli veri türleri için throw işlemi tanımlama

Try ve catch yapısının try kod bloğu içeriğinin yer aldığı bir fonksiyonda sadece belirli veri türleri için throw işlemi tanımlayabiliriz. Bu işlem için fonksiyon bildiriminde throw yapısı kullanılır.

Fonksiyon bildiriminin genel yapı aşağıda gösterilmektedir.

veri-türü fonk-adı(parametreler) throw(veri-türü1, veri-türü2, ...) 
{
  // fonksiyon kod bloğu
}

Burada, throw ifadesinden sonra parantez için de yer alan veri türleri fonksiyon tarafından throw işleminde kullanılabilir. Tanımlanmamış veri türleri kullanılması programın anormal bir şekilde sona ermesine neden olur. Herhangi bir veri türü tanımlanmadığında, fonksiyon hiçbir veriye throw anahtar kelimesi ile işlem yapamaz.

Fonksiyon tarafından tanımlanmamış bir veri türü için throw işlemi yapıldığında, unexpected() fonksiyonu yoluyla abort() fonksiyonunun çağrılmasına neden olur. Bu fonksiyon da programı anormal bir şekilde sonlandırır.

Şimdi, sadece int ve float veri türleri için throw işlemi yapma olanağı sağlayan bir fonksiyonun kullanılmasını bir örnek üzerinde incelemeye çalışalım:


#include<iostream>

using namespace std;

void deger_kontrol(int id) throw (int, float)
{
  switch (id) {
    case 0: throw 21;              // Normal bir şekilde çalışır.
    case 1: throw 21.75f;          // Normal bir şekilde çalışır.
    case 2: throw 'a';             // Programın anormal bir şekilde sona erdirir.
    case 3: throw "Hata kontrolü"; // Programın anormal bir şekilde sona erdirir.
  }
}

int main(void)
{
  try {
    deger_kontrol(0); // int veri türü için çağrı
  }
  catch (int idc) {
    cout << "int değer hatası: " << idc << endl;
  }
  catch (float fd) {
    cout << "float değer hatası: " << fd << endl;
  }
  catch (char cd) {
    cout << "char değer hatası: " << cd << endl;
  }
  catch (const char *cstr) {
    cout << "Karakter dizisi hatası: " << cstr << endl;
  }

  return 0;
}

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

int değer hatası: 21

Program, try kod bloğunun içinde yer aldığı deger_kontrol() adlı fonksiyonu 0 değerini kullanarak int parametre değeri için çağırır. Fonksiyon bildiriminde int veri türü throw ifadesinden sonra yer aldığından, throw anahtar kelimesi devreye girer ve int veri türü için tanımlanmış olan catch kod bloğu çalışır. Aynı şekilde, float veri türü için de çağrı yapılabilir. Ancak, char ve char * veri türleri için yapılan çağrılarda program anormal bir şekilde sonlandırılır.

Şimdi, sadece int veri türü için throw işlemi yapma olanağı sağlayan bir fonksiyonun kullanılmasını tüm veri türleri için tanımlanmış tek bir catch kod bloğu ile oluşturulan bir örneği incelemeye çalışalım:


#include<iostream>

using namespace std;

template <typename t> void deger_kontrol(t x) throw(int)
{
  throw x;
}

int main(void)
{
  try {
    deger_kontrol(21);                 // Sadece int değer normal çalışır.
    // deger_kontrol(47.52f);          // Program anormal bir şekilde sona erer.
    // deger_kontrol('a');             // Program anormal bir şekilde sona erer.
    // deger_kontrol("Hata kontrolü"); // Program anormal bir şekilde sona erer.
  }
  catch (...) {
    cout << "Hatalı değer!" << endl;
  }

  return 0;
}

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

Hatalı değer!

Program, try kod bloğunun içinde yer aldığı deger_kontrol() adlı bir şablon fonksiyon bildirimi yapar. Sonra, main() fonksiyonu içindeki try kod bloğunun içinde, fonksiyonu 21 değerini kullanarak int parametre değeri için çağırır. Fonksiyon bildiriminde int veri türü throw ifadesinden sonra yer aldığından, throw anahtar kelimesi devreye girer ve tanımlanmış olan catch kod bloğu çalışır. Diğer veri türleri için yapılan çağrılarda program anormal bir şekilde sonlandırılır.

Bir hata için tekrar throw işlemi uygulama

Bir try ve catch yapısının catch kod bloğu içinde yeniden throw işlemi yapılabilir. Bu işlemi gerçekleştirmek için, throw anahtar kelimesi tek başına kullanılır. Bu durumda, hata dıştaki try ve catch yapısına geçer. Böylece bir hataya birden fazla catch kod bloğunun işlem yapması veya bir catch kod bloğu gerekli işlemi yapamadığında dışta kalan catch kod bloğunun işlem yapması sağlanır.

Şimdi, bir hata için tekrar throw işlemi uygulanmasını bir örnek üzerinde incelemeye çalışalım:


#include<iostream>

using namespace std;

template <typename t> void deger_kontrol(t x)
{
  try {
    throw x; // Herhangi bir veri türü kullanılabilir.
  }
  catch (...) {
    cout << "deger_kontrol() fonksiyonu içindeki catch kod bloğu" << endl;
    throw;   // Hataya yeniden throw işlemi uygulama
  }
}

int main(void)
{
  try {
    deger_kontrol(21);
  }
  catch(...) {
    cout << "main() fonksiyonu içindeki catch kod bloğu" << endl;
  }

  return 0;
}

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

deger_kontrol() fonksiyonu içindeki catch kod bloğu
main() fonksiyonu içindeki catch kod bloğu

Program, main fonksiyonu içindeki try ve catch yapısının try kod bloğu içinde yer alan deger_kontrol() adlı şablon fonksiyonun içinde tekrar bir try ve catch yapısı tanımlar. Main() fonksiyonu içindeki ilk try kod bloğu içinde yapılan fonksiyon çağrısında, fonksiyon catch bloğu devreye girer ekrana bir karakter dizisi yazdıktan sonra, throw anahtar kelimesini tek başına kullanarak, program akışını main() fonksiyonu içindeki catch kod bloğuna devreder. Burada, bir karakter dizisini ekrana yazdıktan sonra program sona erer.

Try ve catch bloğu işlemlerinde programın anormal bir şekilde sona ermesi

Try ve catch bloğunda throw anahtar kelimesi ile birlikte kullanılan hata kodunun veri türüne işlem yapacak herhangi bir catch bloğu tanımlanmamış ise, program anormal bir şekilde sona erer. Bu durumda, hata koduna herhangi bir işlem yapılmadığından, standart kütüphane fonksiyonu olan terminate() fonksiyonu devre girer ve abort() fonksiyonunu çağırır.

Try ve catch yapısının try kod bloğu içeriğinin yer aldığı bir fonksiyonda sadece belirli veri türleri için throw işlemi tanımladığımızda, fonksiyon tarafından tanımlanmamış bir veri türü için throw işlemi yapılırsa, unexpected() fonksiyonu yoluyla abort() fonksiyonu çağrılır. Bu fonksiyon da programı anormal bir şekilde sonlandırır.

Terminate() ve unexpected() fonksiyonlarının hata kontrolünü gerçekleştirmek için diğer fonksiyonları çağırır. Terminate() fonksiyonu abort() fonksiyonunu ve unexpected() fonksiyonu terminate() fonksiyonunu çağırır. Bir hata meydana geldiğinde, her iki fonksiyon programın çalışmasını durdurur.

Catch kod bloğu tanımlanmamış veri türü ile throw işleminde programın anormal bir şekilde sona ermesi

Bir try ve catch bloğunda throw anahtar kelimesi ile birlikte kullanılan hata kodunun veri türüne işlem yapacak herhangi bir catch bloğu tanımlanmamış ise, program anormal bir şekilde sona erer. Bu durumda, programın anormal bir şekilde sona ermesi terminate() ve abort() fonksiyonları tarafından kontrol edilir.

Şimdi, bu durumu bir örnek üzerinde incelemeye çalışalım:


#include<iostream>

using namespace std;

int main(void)
{
  int id;

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  try {
    if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
    }
    else {
      throw id;
    }
  }
  catch (float fd) {
    cout << endl << "Girdiğiniz sayı 1-100 arasında değildir!" << endl;
    cout << "Girdiğiniz sayı: " << fd;
  }

  return 0;
}

Program, girilen değer belirtilen aralıkta ise, "Girdiğiniz sayı 1-100 arasındadır!" ifadesini ekrana yazar ve catch kod bloğuna giriş yapılmadan programın çalışması sona erer. Eğer girilen değer belirtilen aralıkta değil ise, throw anahtar kelimesi ile girilen değer kullanılarak int değer için oluşturulan catch kod bloğu çağrılır. Ancak, int veri türü için tanımlanmış catch bloğu olmadığından, program hatalı bir şekilde sona erer.

Terminate() ve unexpected() fonksiyonları tarafından çağrılan fonksiyonları tanımlama

Try ve catch bloğunun kullanıldığı bir programın çalışması anormal bir şekilde sona erdiğinde, terminate() ve unexpected() fonksiyonları tarafından çağrılan fonksiyonları değiştirerek, programın hata işleme sisteminin tüm kontrolünü ele almasını sağlayabiliriz.

Terminate() fonksiyonunun çağırdığı fonksiyonu değiştirmek için, aşağıda genel yapısı gösterilen set_terminate() fonksiyonu kullanılır:

terminate_handler set_terminate(terminate_handler yenifonk) throw();

Burada, yenifonk yeni fonksiyonu gösteren bir işaretçidir. Set_terminate() fonksiyonu önceki fonksiyonu gösteren bir işaretçiyi geri döndürür. Yeni fonksiyon aşağıdaki şekilde tanımlanan terminate_handler türünde olmalıdır:

typedef void (*terminate_handler) ();

Burada tanımlanan fonksiyonun tek görevi, programın çalışmasını durdurmaktır. Programa geri dönmemeli veya herhangi bir şekilde devam etmesini sağlamalıdır.

Unexpected() fonksiyonunun çağırdığı fonksiyonu değiştirmek için, aşağıda genel yapısı gösterilen set_unexpected() fonksiyonu kullanılır:

unexpected_handler set_unexpected(unexpected_handler yenifonk) throw();

Burada, yenifonk yeni fonksiyonu gösteren bir işaretçidir. Set_unexpecte() fonksiyonu önceki fonksiyonu gösteren bir işaretçiyi geri döndürür. Yeni fonksiyon aşağıdaki şekilde tanımlanan unexpected_handler türünde olmalıdır:

typedef void (*unexpected_handler) ();

Burada tanımlanan fonksiyonun tek görevi, programın çalışmasını durdurmak veya terminate() fonksiyonunu çağırmaktır. Ancak, programa geri dönüş yapmamalıdır.

Set_terminate() ve set_unexpected() fonksiyonlarını kullanmak için programda <exception> başlık dosyasını tanımlamak gerekir.

Şimdi, terminate() fonksiyonunun çağırdığı fonksiyonu değiştirildiği bir örneği incelemeye çalışalım:


#include<iostream>
#include <exception>

using namespace std;

void fonk_yeni(void) {
  cout << endl << "Yeni terminate() fonksiyonu" << endl;
  abort();
}

int main(void)
{
  int id;

  set_terminate(fonk_yeni); // Yeni terminate() fonksiyonu tanımlama

  cout << "1-100 arasında bir sayı giriniz: ";
  cin >> id;

  try {
    if (id >= 1 && id <= 100) {
      cout << endl << "Girdiğiniz sayı 1-100 arasındadır!" << endl;
    }
    else {
      throw id;
    }
  }
  catch (float fd) {
    cout << endl << "Girdiğiniz sayı 1-100 arasında değildir!" << endl;
    cout << "Girdiğiniz sayı: " << fd;
  }

  return 0;
}

Program, girilen değer belirtilen aralıkta ise, "Girdiğiniz sayı 1-100 arasındadır!" ifadesini ekrana yazar ve catch kod bloğuna giriş yapılmadan programın çalışması sona erer.

Eğer girilen değer belirtilen aralıkta değil ise, throw anahtar kelimesi ile girilen değer kullanılarak int değer için oluşturulan catch kod bloğu çağrılır. Ancak, int veri türü için tanımlanmış catch bloğu olmadığından, program hatalı bir şekilde sona erer ve aşağıdaki ifadeleri ekrana yazar.

1-100 arasında bir sayı giriniz: 121
Yeni terminate() fonksiyonu