Différence: std :: runtime_error vs std :: exception ()

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 en C ++).

std::runtime_error est une classe plus spécialisée, std::runtime_error de std::exception , destinée à être lancée en cas de diverses erreurs d’ exécution . Il a un double objective. Il peut être lancé par lui-même 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’exception à partir de std::runtime_error , de même que vous pouvez définir vos propres classes d’exception en fonction de std::exception .

Tout comme std::runtime_error , la bibliothèque standard contient std::logic_error , également descendant de std::exception .

Le but de cette hiérarchie est de donner à l’utilisateur la possibilité d’utiliser toute la puissance du mécanisme de gestion des exceptions C ++. Étant donné que la clause ‘catch’ peut intercepter des exceptions polymorphes, l’utilisateur peut écrire des clauses ‘catch’ pouvant intercepter des types d’exception à partir d’une sous-arborescence spécifique de la hiérarchie des exceptions. Par exemple, catch (std::runtime_error& e) intercepte toutes les exceptions de la sous-arborescence std::runtime_error , laissant passer toutes les autres (et remontant la stack des appels).

PS La conception d’une hiérarchie de classes d’exceptions utile (qui ne vous permet d’attraper que les types d’exception qui vous intéressent à chaque sharepoint votre code) est une tâche non sortingviale. Ce que vous voyez dans la bibliothèque C ++ standard est une approche possible, proposée par les auteurs du langage. Comme vous le voyez, ils ont décidé de diviser tous les types d’exceptions en “erreurs d’exécution” et en “erreurs logiques” et de vous laisser partir de là avec vos propres types d’exceptions. Bien entendu, il existe 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 noté dans leur réponse et leurs commentaires ci-dessous, le constructeur de la classe d’ exception ne prend aucun argument selon la norme C ++. Microsoft C ++ a un constructeur prenant des arguments dans la classe des exception , mais ce n’est pas standard. La classe runtime_error a un constructeur qui prend les arguments ( char* ) sur les deux plates-formes, Windows et Linux. Pour être portable, mieux vaut utiliser runtime_error .

(Et rappelez-vous que, simplement parce qu’une spécification de votre projet indique que votre code ne doit pas être exécuté sur Linux, cela ne signifie pas qu’il ne doit jamais s’exécuter sous Linux.)

std :: exception doit être considéré (notez le considéré) comme la base abstraite de la hiérarchie des exceptions standard. C’est parce qu’il n’y a pas de mécanisme pour 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 les applications simples, il peut s’agir de tout ce dont vous avez besoin.

std :: runtime_error d’autre part a des constructeurs valides qui acceptent une chaîne en tant que message. Quand on appelle what () un pointeur de caractère const est renvoyé qui pointe sur une chaîne C qui a la même chaîne que celle qui a été 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"; }