Question

Dans mon projet, nous avons une exception de base. Pour la manipulation montrant les boîtes de dialogue d'erreur, connectez-vous et tel. Im la recherche d'une façon de gérer toutes les classes dérivées de cette exception, je pensais que cela fonctionnerait:

try
{
  main_loop();
}
catch (const MyExceptionBase* e)
{
  handle_error(e);
}

Comme tous les cas de l'enfant jeté pourrait être représenté par un pointeur vers son parent. Mais non, quand des exceptions sont levées maintenant, son une exception non gérée.

Pourquoi est-ce? Ne c ++ ne lancer des exceptions comme références? De ce fait rendu mon bloc catch inutile? Mais alors pourquoi cette même compilation en premier lieu?

La seule autre façon que je peux penser est la suivante:

try
{
  main_loop();
}
catch (const ExceptionA& e)
{
  handle_error(e);
}
catch (const ExceptionB& e)
{
  handle_error(e);
}
catch (const ExceptionC& e)
{
  handle_error(e);
}

Ce qui semble un peu laid. Quelle est la bonne façon de le faire? Ne pas avoir une classe d'exception de base? Ou peut-il être résolu de la manière que je veux?

Ps. Qu'est-ce que handle_error() fait est simplement d'utiliser la fonction de la classe de base display_message_box() et arrêter proprement le programme

Était-ce utile?

La solution

Il suffit de mélanger les deux approches: utiliser la classe de base, et utiliser une référence

.
try
{
  main_loop();
}
catch (const MyExceptionBase& e)
{
  handle_error(e);
}

BTW C ++ peut attraper des pointeurs, si vous les jeter. Il est conseillé de ne pas bien.

Autres conseils

Votre meilleur pari est d'attraper la référence de base. Mais s'il vous plaît le faire par référence, et non par le pointeur. Exemple

try
{
  main_loop();
}
catch (const MyExceptionBase& e)
{
  handle_error(e);
}

Le problème avec la capture d'une exception par pointeur est qu'il doit être jeté par le pointeur. Cela signifie qu'il sera créé avec le nouveau.

throw new ExceptionA();

Cela laisse un problème assez important car il doit être supprimé à un moment donné ou si vous avez une fuite de mémoire. Qui devrait être responsable de la suppression de cette exception? Il est généralement difficile d'obtenir ce droit qui est la raison pour laquelle la plupart des gens attrapent par référence.

En général en C ++, vous devriez ...

  

Catch par référence, par un jet valeur

Vous ne pouvez utiliser catch( const sometype* ptr ) si vous jetez des pointeurs, ce qui est à déconseiller dans 99% des cas.

La raison fonctionne catch( const sometype& ptr ) est parce que les valeurs r sont implicitement convertibles en références constantes.

Cela devrait fonctionner:

try {
  main_loop();
} catch (const MyExceptionBase &e) {
  handle_error(e);
}

Je suppose que EXCEPTIONNELLE / B / C héritons tous de MyExceptionBase ... Je pense que cela devrait fonctionner très bien.

PS: vous voudrez peut-être envisager d'avoir inhert de MyExceptionBase de std :: exception et

.

Je suis surpris que votre exemple original ne fonctionne pas. Ce qui suit fonctionne (au moins avec g ++):

class Base { public: virtual ~Base () {} };
class Derived : public Base {};

int main ()
{
  try
  {
    throw new Derived ();
  }
  catch (Base const * b)
  {
    delete b;
  }
}

Je suis aussi assez sûr que cela est destiné à fonctionner comme par une balle sous 15,3 / 3:

  

le gestionnaire est de type CV1 CV2 T * et E est un type pointeur qui peut être converti en le type du gestionnaire par une ou les deux

Êtes-vous héritez du type d'exception de base par héritage public? La classe de base doit être une base accessible et cela arrêterait votre exception d'être pris.

Comme par toutes les autres réponses ici, lancer / attraper par référence a un avantage que vous n'avez pas à vous soucier de la propriété de la mémoire etc. Mais si l'exemple ci-dessus fonctionne pas - je ne sais pas pourquoi l'exemple de référence fonctionnerait.

Comme d'autres l'ont mentionné, vous devriez prendre une référence à l'exception de la classe de base.

Quant à savoir pourquoi il compile en premier lieu, contrairement à Java, il n'y a aucune restriction sur les types peuvent être projetés ou capturés. Ainsi, vous pouvez mettre dans un bloc catch pour tout type, même si elle n'a jamais jeté, et votre compilateur compiler heureusement il. Puisque vous peut jeter par pointeur, vous pouvez également attraper par pointeur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top