8
votes

Comment simuler l'exception intérieure en C ++

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. XXX

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?


3 commentaires

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; serait mieux. J'aimerais vraiment voir un cas d'utilisation pour quand vous voudriez envelopper une exception.


6 Réponses :


1
votes

aussi je ne suis pas sûr que le objet temporaire qui est jeté de Func1 survivra même après Func2 lancer?

Non. Sauf si vous retirez l'exception avec lancer; . Vous pouvez implémenter cela si vous n'auriez autorisé que certains types d'exceptions (limité).


0 commentaires

0
votes
//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...

0 commentaires

0
votes

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();
}


0 commentaires

3
votes

Vous devez également consulter Boost Exception pour une solution alternative à l'emballage.


0 commentaires

0
votes

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
}


0 commentaires

4
votes

Depuis C ++ 11, vous avez de nouvelles options:

  1. 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))
        {}
    
    };
    
  2. ou vous pouvez simplement utiliser STD :: NEST_EXCEPTION . LI > ol> p>


0 commentaires