Fondamentalement, je veux simuler .NET Exception.innnerexception en C ++. Je veux attraper une exception à partir de la couche inférieure et enveloppez-la avec une autre exception et jetez à nouveau jusqu'à la couche supérieure. Le problème ici est que je ne sais pas comment envelopper l'exception accrochée dans une autre exception. Dans la liste Code ci-dessus, je ne sais pas comment initialiser le membre "InnErException" lorsqu'il y a Aucune exception interne. De plus, je ne suis pas sûr que l'objet temporaire qui soit lancé à partir de Func1 survivra même après le lancer de Func2? P> P>
6 Réponses :
aussi je ne suis pas sûr que le objet temporaire qui est jeté de Func1 survivra même après Func2 lancer? p> blockQuote>
Non. Sauf si vous retirez l'exception avec
lancer; code>. Vous pouvez implémenter cela si vous n'auriez autorisé que certains types d'exceptions (limité). P>
//inversion of the problem :) struct base_exception : public std::exception { std::list<base_exception*> snowball; base_exception() { } void add(base_exception* e) { snowball.push_back(e); } }; void func2() { func2_exception e; e.add(new func2_exception()); throw e; } void func1() { try { func2(); } catch(base_exception& e) { e.add(new func1_exception()); throw e; } } int main(void) { try { func1(); } catch(base_exception& e) { std::cout << "Got exception" << std::endl; //print info in the direct order of exceptions occurence foreach(base_exception* exception, e.snowball) { std::cout << exception->what(); std::cout << "next exception was:" << std::endl; } } } hmmmm...
Un problème avec l'exception interne est la possibilité de le jeter à nouveau tout en maintenant un comportement polymorphe.
Cela peut être (quelque peu) en gérant en réalité la durée de vie de l'exception et de fournir des copies polymorphes. P>
try { // some code } catch(exception& e) { throw ExceptionPointer(e.clone()); } // later on try { } catch(ExceptionPointer& e) { e.throwInner(); }
Vous devez également consulter Boost Exception pour une solution alternative à l'emballage. P>
Comme indiqué par d'autres, boost :: Exception est une bonne option. Cependant, comme toutes les options qui utilisent une approche commune de la classe de base, elles s'appuient sur toutes les exceptions levées dérivées de cette classe de base. Si vos gestionnaires de capture intermédiaires doivent ajouter des informations à une exception d'une bibliothèque tierce partie, elle ne fonctionnera pas.
Une option qui pourrait être suffisante consiste à avoir des gestionnaires de capture intermédiaires comme celui-ci: P>
catch (std::exception& ex) { std::string msg = ex.what(); msg.append(" - my extra info"); ex = std::exception(msg.c_str()); // slicing assignment throw; // re-throws 'ex', preserving it's original type }
Depuis C ++ 11, vous avez de nouvelles options:
Vous pouvez utiliser std :: exception_ptr . p>
L'exception est alors conserver jusqu'à la dernière exception_ptr. L'exception est détruite. P>
struct base_exception : public std::exception { std::exception_ptr InnerException; base_exception() {} base_exception(std::exception& innerException) : InnerException(std::make_exception_ptr(innerException)) {} };
Pas vraiment une réponse, mais vous pouvez être intéressé par l'approche Boost.Exception: boost.org/doc/libs/release/libs/exception/index.html
Je ne comprends pas pourquoi fonctionnerait une exception capturer si cela ne sait pas quoi faire avec ça. Juste pour collecter une pile d'appels?
@Assk: bonne question. Généralement, vous voulez attraper une exception où vous pouvez le gérer le mieux, puis y faire face là-bas. Je peux comprendre l'intercepter pour le loger, mais vous penseriez alors une ligne
à lancer; code> serait mieux. J'aimerais vraiment voir un cas d'utilisation pour quand vous voudriez envelopper une exception.