Pourquoi les exceptions en C ++ ne sont-elles pas vérifiées par le compilateur?

C ++ fournit une syntaxe pour les exceptions vérifiées, par exemple:

void G() throw(Exception); void f() throw(); 

Toutefois, le compilateur Visual C ++ ne les vérifie pas; l’indicateur de jet est simplement ignoré. À mon avis, cela rend la fonctionnalité d’exception inutilisable. Ma question est donc la suivante: existe-t-il un moyen de faire en sorte que le compilateur vérifie si les exceptions sont correctement capturées / retransmises? Par exemple, un plug-in Visual C ++ ou un autre compilateur C ++.

PS Je veux que le compilateur vérifie si les exceptions sont correctement détectées, sinon vous vous retrouvez dans une situation où vous devez attraper chaque appel de fonction que vous effectuez, même si elles déclarent explicitement qu’elles ne lanceront rien .

Mise à jour: le compilateur Visual C ++ affiche un avertissement lors du lancement dans une fonction marquée avec throw (). C’est génial, mais malheureusement, l’avertissement ne s’affiche pas lorsque vous appelez une sous-routine qui pourrait lancer. Par exemple:

 void f() throw(int) { throw int(13); } void h() throw() { g(); } //no warning here! 

Les spécifications d’exception sont plutôt inutiles en C ++.

Il n’est pas obligatoire qu’aucune autre exception ne soit levée, mais simplement que la fonction globale Répertoire unexpected() soit appelée (ce qui peut être défini)

L’utilisation de spécifications d’exception se résume principalement à vous faire croire (ou à vos pairs) à un faux sentiment de sécurité. Mieux vaut simplement ne pas déranger.

Ce qui est amusant, c’est que Java a vérifié les exceptions et les programmeurs Java les détestent aussi.

Les spécifications d’exception en C ++ sont inutiles pour 3 raisons:

1. Les spécifications d’exception C ++ empêchent l’optimisation.

À l’exception peut-être de throw (), les compilateurs insèrent du code supplémentaire pour vérifier que, lorsque vous lancez une exception, elle correspond à la spécification d’exception des fonctions lors du déroulement de la stack. Façon de rendre votre programme plus lent.

2. Les spécifications d’exception C ++ ne sont pas appliquées par le compilateur

En ce qui concerne votre compilateur, les éléments suivants sont syntaxiquement corrects:

 void AStupidFunction() throw() { throw 42; } 

Pire encore, rien ne se passe si vous enfreignez une spécification d’exception. Votre programme se termine juste!

3. Les spécifications d’exception C ++ font partie de la signature d’une fonction.

Si vous avez une classe de base avec une fonction virtuelle et essayez de la remplacer, les spécifications d’exception doivent correspondre exactement. Donc, vous feriez mieux de planifier à l’avance, et c’est toujours douloureux.

 struct A { virtual int value() const throw() {return 10;} } struct B : public A { virtual int value() const {return functionThatCanThrow();} // ERROR! } 

Les spécifications d’exception vous posent ces problèmes et le gain pour les utiliser est minime. En revanche, si vous évitez complètement les spécifications d’exception, le codage est plus facile et vous évitez ce genre de choses.

Regardez ceci:

http://www.gotw.ca/publications/mill22.htm

essentiellement, les spécifications d’exception sont impraticables / inutilisables, mais cela ne rend pas les exceptions irréalisables.

En ce qui concerne votre question, il est impossible de demander au compilateur de vérifier que chaque type renvoyé se trouve plus haut dans le code, ce qui rend la compilation difficile et impossible pour un code destiné à être utilisé dans une bibliothèque ( où le niveau supérieur n’est pas disponible au moment de la compilation). Si vous voulez être sûr que tout est pris, collez une capture (…) tout en haut de votre code.

Pour détecter avant l’exécution des cas tels que …

 extern void f() throw (class Mystery); void g() throw() { f() ; } 

… vous avez besoin d’ une parsing statique . Oui, le compilateur fait beaucoup d’parsings statiques, mais parce que la norme est “raise std :: SOUVENIR si le lancement ne correspond pas”, et il est parfaitement légal d’écrire une routine qui lance un object qui ne correspond pas au spécificateur , les implémenteurs du compilateur ne font ni avertissement ni remarque.

Les outils d’parsing statique qui prétendent fournir un service d’alerte incluent la charpente de Gimpel Software pour C ++ …

1560 Exception non détectée ‘Nom’ non sur la liste de diffusion pour la fonction ‘Symbole’

et, selon cette réponse à une question antérieure, QA C ++ .

Parce que la norme le dit. La déclaration d’exception ne signifie pas qu’aucune autre exception ne sera lancée. Cela signifie que si une exception non déclarée est levée, il y aura une fonction globale spéciale appelée auprès de laquelle on ne pense pas () , qui par défaut termine le programme. En général, la déclaration des exceptions dans les fonctions est déconseillée (sauf peut-être pour la liste des exceptions vides) car le comportement standard n’est pas très utile.

Je ne peux pas vérifier cela à cause d’une installation MSVC, mais êtes-vous vraiment sûr que le compilateur ignore la spécification de throw ()?

Cette page MSDN suggère que Microsoft a connaissance de throw () et attend de son compilateur qu’il le gère correctement. Eh bien, presque la note sur la façon dont ils s’écartent de la norme ANSI / ISO dans certains détails.

Edit: En pratique, cependant, je suis d’accord avec Pasortingck: les spécifications d’exception sont pour la plupart inutiles.