8
votes

Traitement des exceptions avant et après la main

est-il possible de gérer des exceptions dans ces scénarios:

  1. jeté du constructeur avant d'entrer dans la main principale ()
  2. jeté du destructeur après avoir quitté le principal ()

3 commentaires

Alors une base sur toutes les suggestions, est-elle prudente de conclure que: (1) Même avec un bloc d'essais autour du constructeur / destructeur, l'exception sera toujours retirée. (2) Si cela se produit en dehors de la portée principale (), c'est-à-dire l'initialisation de l'objet global, ou une désinalisation automatique de l'objet normal lors de la résiliation, une exception ne peut pas être capturée.


Pas assez. Les ctors peuvent seulement indiquent une défaillance dans des exceptions, car vous ne pouvez pas avoir d'extrémité cort sans construire un objet; Donc, attraper des exceptions projetées par un CTOR ne doit pas violer cela. Vous DO Attrapez toute exception potentielle d'un DTOR, car les DTOR sont appelés dans le cadre du déroulement de la pile (ce qui se produit lorsque des exceptions sont lancées). Si vous ne le faites pas, alors vous avez Deux Exceptions actifs en même temps, qui vous obtient STD :: Terminez ().


Je lisons ce sujet du titre de Stroustrup. De son explication, tout ressemble à une conception douloureuse soumise à moi.


4 Réponses :


0
votes

Il serait peut-être possible de définir un gestionnaire d'exception avant la construction / la destruction des objets en question, qu'il faut pouvoir gérer ces exceptions.

Pour les constructeurs, il existe une nouvelle syntaxe étrange qui permet de prendre des exceptions dans le constructeur. Je ne sais pas comment cela fonctionne, et ce n'est pas communément mis en œuvre dans de nombreux compilateurs.

Pour les destructeurs, vous devez envelopper le contenu du destructeur d'un essai {code (); } Catch (...) {} bloc. Ce qui peut ne pas toujours être le comportement souhaité, en fonction de ce que vous voulez réaliser dans ce destructeur.


1 commentaires

"Nouveau" Comme depuis plus de 15 ans? : P it est communément implémenté et fait partie de la norme C ++.



22
votes
  1. Vous pouvez conclure votre constructeur avec une capture d'essai à l'intérieur. Li>
  2. Non, vous devriez JAMAIS FORT> Autoriser une exception lancer dans un destructeur. Li>

    La caractéristique drôle moins connue de la manière d'intégrer les captures d'essai dans un constructeur: p> xxx pré>

    oui, ce est fort> valide C ++. L'avantage supplémentaire ici est le fait que l'essai attrape des exceptions jetées par les constructeurs des membres de la classe EM>, même si elles ne sont pas mentionnées dans l'initialiseur CTOR ou qu'il n'y a pas d'initialiseur CTOR: P>

    struct Throws {
      int answer;
      Throws() : answer(((throw std::runtime_error("whoosh!")), 42)) {}
    };
    
    struct Contains {
      Throws baseball;
      Contains() try {} catch (std::exception& e) { std::cerr << e.what() << '\n'; }
    };
    


9 commentaires

J'ai été surpris quand je l'ai appris aussi :). C'est l'une de ces caractéristiques moins connues ...


Ah, oublié des initialisateurs facultatifs qui passent. Maintenant c'est complètement ésotérique.


Fonction Try-Blocks fonctionne également pour presque toutes les fonctions, y compris la principale (où vous devez en en avoir toujours un).


Mais seulement dans les constructeurs, ils ont le bénéfice réel d'envelopper l'initialisation des objets.


Notez que l'exception sera toujours retirée à la fin du constructeur (pour empêcher qu'il y ait un objet avec des membres non initialisés).


Vous n'avez pas utilisé cette "fonctionnalité moins connue" dans l'échantillon. J'ai essayé l'échantillon en VC2008, mais l'exception s'est propagée à la principale.


Jagannath: Comme James l'a souligné, vous ne pouvez pas faire taire des exceptions des ctors des membres de données, vous doit les propager. La sortie sera toujours écrite à StDerr, pour montrer qu'il a été attrapé, cependant.


Le point 2 pourrait utiliser un tweak: "Non, vous ne devez jamais permettre à des exceptions d'échapper à un destructeur." Une fonction, appelée d'un DTOR, qui jette bien, le DTOR doit simplement s'assurer de le gérer.


Je me demande si un appel à quitter () serait également correct dans le bloc d'essai du constructeur? En tout état de cause, il ne semble que la récupération, car il n'ya pas de lieu de continuer à partir de même que le programme n'a même pas commencé à courir. Mais on ne veut probablement pas récupérer d'erreurs fatales dans la construction globale de toute façon ...



4
votes

Oui: N'utilisez pas d'objets globaux dangereux!


2 commentaires

C'est la meilleure réponse (après avoir ajouté "ou des singletons dangereux"), mais je suis hors des voix pour les 14 prochaines heures!


+1: Au nom de Roger - Cependant, j'aimerais souligner qu'il existe des situations que cela est impossible, surtout si vous utilisez des API bizarres qui prennent la décision pour vous.



0
votes

Réponse courte: non.

Tout objet global qui jette une exception dans son constructeur provoquera une exception non gérée (c'est-à-dire terminer être appelé).

Toute classe qui jette une exception dans son destructeur est une classe brisée.

Utiliser le modèle singleton plutôt que les globaux vous donnera plus d'options.


4 commentaires

Je trouve le contraire: les singletons réduisent les options. Mettre des objets au niveau de l'application en tant que variables locales dans les travaux principaux magnifiques.


@Roger Je ne pense pas que nous ne sommes pas d'accord - je n'ai dit que des singletons vous donnent plus d'options que les globaux.


Non, je pense que les singletons réduisent les options par rapport aux objets globaux, comme au moins avec des globaux, vous pouvez tous les mettre dans une TU pour contrôler l'ordre d'initialisation et d'autres choses.


Oh, nous ne sommes pas d'accord alors ;-). Les singletons ne sont créés que si et en cas de besoin, et dans le cas rare d'un singleton en fonction d'une autre, cela fonctionne automatiquement, plutôt que les instances d'objet doivent être soigneusement commandées. Les singletons peuvent également être gardés privés dans un domaine de code particulier, plutôt que de devoir être largués dans Main.cpp. Et WRT à la question initiale, une variation du modèle singleton vous permettrait de gérer un singleton ne pas construire correctement (peut-être gris l'interface utilisateur et afficher une erreur plutôt que de se bloquer).