Quelle est la différence entre std::runtime_error
et std::exception
? Quelle est l'utilisation appropriée pour chacun? Pourquoi sont-ils différents en premier lieu?
std::exception
Est la classe dont le seul but est de servir de classe de base dans la hiérarchie des exceptions. Il n'a pas d'autres utilisations. En d'autres termes, conceptuellement, il s'agit d'une classe abstraite (même si elle n'est pas définie en tant que classe abstraite au sens C++ du terme).
std::runtime_error
Est une classe plus spécialisée, dérivée de std::exception
, Destinée à être levée en cas de diverses erreurs d'exécution . Il a un double objectif. Elle peut être générée seule ou servir de classe de base à divers types d'exceptions d'erreur d'exécution encore plus spécialisés, tels que std::range_error
, std::overflow_error
, Etc. Vous pouvez définir vos propres classes d'exceptions. descendant de std::runtime_error
, ainsi que vous pouvez définir vos propres classes d’exception descendant de std::exception
.
Tout comme std::runtime_error
, La bibliothèque standard contient std::logic_error
, Descendant également de std::exception
.
L'intérêt de cette hiérarchie est de donner à l'utilisateur la possibilité d'utiliser toute la puissance du mécanisme de traitement des exceptions C++. Étant donné que la clause 'catch' peut intercepter les exceptions polymorphes, l'utilisateur peut écrire des clauses 'catch' pouvant intercepter les types d'exception d'un sous-arbre spécifique de la hiérarchie des exceptions. Par exemple, catch (std::runtime_error& e)
interceptera toutes les exceptions de la sous-arborescence std::runtime_error
, Laissant passer toutes les autres (et survolant la pile d'appels).
P.S. Concevoir une hiérarchie de classes d’exception utile (qui vous permettrait de ne capturer que les types d’exception qui vous intéressent à chaque point de votre code) est une tâche non triviale. Ce que vous voyez dans la bibliothèque standard C++ est une approche possible, qui vous est proposée par les auteurs du langage. Comme vous le voyez, ils ont décidé de scinder tous les types d'exceptions en "erreurs d'exécution" et "erreurs de logique" et de vous permettre de poursuivre à partir de là avec vos propres types d'exceptions. Il existe bien sûr d'autres moyens de structurer cette hiérarchie, ce qui pourrait être plus approprié dans votre conception.
Mise à jour: Portabilité Linux vs Windows
Comme Loki Astari et unixman83 l’ont indiqué dans leur réponse et leurs commentaires ci-dessous, le constructeur de la classe exception
ne prend aucun argument conformément au standard C++. Microsoft C++ a un constructeur qui prend des arguments dans la classe exception
, mais ce n'est pas standard. La classe runtime_error
A un constructeur qui prend des arguments (char*
) Sur les deux plates-formes, Windows et Linux. Pour être portable, utilisez mieux runtime_error
.
(Et rappelez-vous, ce n’est pas parce qu’une spécification de votre projet indique que votre code ne doit pas être exécuté sous Linux que cela ne signifie pas qu’il ne doit jamais être exécuté sous Linux.)
std :: exception doit être considéré (notez le considéré) la base abstraite de la hiérarchie des exceptions standard. En effet, il n’existe aucun mécanisme permettant de transmettre un message spécifique (pour ce faire, vous devez dériver et spécialiser quoi ()). Il n'y a rien qui vous empêche d'utiliser std :: exception et pour des applications simples, c'est peut-être tout ce dont vous avez besoin.
en revanche, std :: runtime_error a des constructeurs valides qui acceptent une chaîne en tant que message. Lorsque what () est appelé, un pointeur de caractère constant est renvoyé qui pointe sur une chaîne C possédant la même chaîne que celle transmise au constructeur.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}