Risposte:
std::exceptionè la classe il cui unico scopo è quello di fungere da classe base nella gerarchia delle eccezioni. Non ha altri usi. In altre parole, concettualmente è una classe astratta (anche se non è definita come classe astratta nel significato C ++ del termine).
std::runtime_errorè una classe più specializzata, discendente da std::exception, destinata a essere lanciata in caso di vari errori di runtime . Ha un duplice scopo. Si può essere gettato da solo, oppure può servire come una classe base a vari tipi ancora più specializzati di eccezioni di errore di runtime, ad esempio std::range_error, std::overflow_errorecc È possibile definire le proprie classi di eccezioni che scende da std::runtime_error, così come è possibile definire la propria eccezione classi discendenti da std::exception.
Proprio come std::runtime_error, contiene la libreria standard std::logic_error, anche discendente std::exception.
Il punto di avere questa gerarchia è dare all'utente la possibilità di utilizzare tutta la potenza del meccanismo di gestione delle eccezioni C ++. Poiché la clausola "catch" può intercettare le eccezioni polimorfiche, l'utente può scrivere clausole "catch" in grado di catturare i tipi di eccezione da una sottostruttura specifica della gerarchia di eccezioni. Ad esempio, catch (std::runtime_error& e)catturerà tutte le eccezioni dalla std::runtime_errorsottostruttura, consentendo a tutti gli altri di passare (e volare più in alto nello stack di chiamate).
PS Progettare una gerarchia di classi di eccezioni utile (che ti consenta di catturare solo i tipi di eccezione che ti interessano in ogni punto del tuo codice) è un'attività non banale. Quello che vedi nella libreria C ++ standard è un possibile approccio, offerto dagli autori del linguaggio. Come vedi, hanno deciso di dividere tutti i tipi di eccezione in "errori di runtime" e "errori logici" e da lì puoi procedere con i tuoi tipi di eccezione. Esistono, ovviamente, modi alternativi per strutturare quella gerarchia, che potrebbe essere più appropriato nel tuo progetto.
Aggiornamento: portabilità Linux vs Windows
Come hanno notato Loki Astari e unixman83 nella loro risposta e nei commenti che seguono, il costruttore della exceptionclasse non accetta alcun argomento secondo lo standard C ++. Microsoft C ++ ha un costruttore che accetta argomenti nella exceptionclasse, ma questo non è standard. La runtime_errorclasse ha un costruttore che prende argomenti ( char*) su entrambe le piattaforme, Windows e Linux. Per essere portatile, un uso migliore runtime_error.
(E ricorda, solo perché una specifica del tuo progetto dice che il tuo codice non deve essere eseguito su Linux, non significa che non debba mai essere eseguito su Linux.)
std::exception. Certo, tutto stdgetta delle classi derivate di ciò, ma non c'è assolutamente alcun motivo per lanciare solo std::exceptionoggetti derivati.
std::exceptiondovrebbe essere considerata (nota la considerata) la base astratta della gerarchia di eccezioni standard. Questo perché non esiste alcun meccanismo per passare un messaggio specifico (per fare ciò è necessario derivare e specializzarsi what()). Non c'è nulla che ti impedisca di usare std :: exception e per le applicazioni semplici potrebbe essere tutto ciò di cui hai bisogno.
std::runtime_errord'altra parte ha costruttori validi che accettano una stringa come messaggio. Quando what()viene chiamato viene restituito un puntatore const char che punta a una stringa C che ha la stessa stringa passata nel costruttore.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string). Ora mi rendo conto che devo lanciare std::runtime_errorse voglio che il mio codice funzioni in Linux (GCC).