C++ Try-Catch

Da Andreabont's Wiki.

Il costrutto try-catch permette la gestione delle eccezioni in C++. Una eccezione è una return multi-livello da usare in caso di emergenza, tendenzialmente per comunicare che si è presentato un errore, che localmente non è possibile gestire, ad uno dei chiamanti che potrebbe riuscire a gestire l'errore. La gestione di una eccezione è onerosa a livello computazionale, quindi, come suggerisce il nome, deve essere usata in casi eccezionali.

Parole chiave

Throw

La parola chiave throw seguita da una variabile, (che può essere di qualsiasi tipo, solitamente un oggetto derivato da exception) permette di lanciare una nuova eccezione. All'esecuzione di questa istruzione si esce immediatamente da ogni contesto, salendo di livello fino ad un catch in grado di catturare l'eccezione. Se non viene catturata una eccezione provoca la terminazione del programma in corso.

Try

La sezione try resta in ascolto di tutte le eccezioni lanciate al suo interno, indipendentemente dal livello, e passa le eccezioni trovate alla sezione catch.

Catch

Una eccezione si porta dietro una variabile, la quale viene "catturata" dalla sezione catch. E' possibile filtrare le eccezioni in base alla variabile ritornata, questo avviene specificando più sezioni catch indicando per ognuna il tipo della variabile atteso. Se si indica ... come tipo è inteso come "tutte le eccezioni non catturate precedentemente". Una volta che l'eccezione è stata catturata è possibile rilanciarla semplicemente con la sola parola chiave throw.

Noexcept

Una funzione o metodo dichiarate noexcept vengono escluse dal sistema di gestione delle eccezioni del C++, da usare solamente se si è sicuri che contengono codice che non lancia eccezioni. Ogni eventuale eccezione lanciata al suo interno provoca l'immediata interruzione del programma, anche se è dichiarato un blocco catch che potrebbe gestirla.

Codice di esempio

Try-Catch a livello di porzione di codice

try {
    // Codice...
}
catch(std::exception& e) {
    // Gestione errori...
}
catch(...) {
    // Segnalo presenza errori e rilancio.
    throw;
}

Try-Catch a livello di metodo/funzione

int funzione() try {
    // Codice funzione ...
}
catch(...) {
    // Gestione errori...
}

Sospensione di una eccezione

In C++11 è possibile "sospendere" una eccezione attiva, e continuare l'esecuzione, per poi rilanciarla successivamente.

#include <iostream>
#include <exception>
#include <stdexcept>

void fai_altro(std::exception_ptr eptr) try {
   std::cout << "Eccezione passata alla funzione" << std::endl;
   std::rethrow_exception(eptr); // Rilancia l'eccezione catturata
} catch (std::exception& e) {
   std::cout << "Eccezione catturata" << std::endl;
}

int main(){

   try {
      throw std::out_of_range("ERRORE");
   } catch (std::exception& e) {
      std::exception_ptr eptr; // Tipo "puntatore" all'eccezione
      eptr = std::current_exception(); // Salva l'eccezione catturata
      fai_altro(eptr); // Passa il puntatore dell'eccezione ad una funzione
   }

}