10 votes

Erreur de spécification de lancer en C++.

Le code suivant génère l'erreur "Looser throw specifier error". Pouvez-vous m'aider à surmonter cette erreur ?

class base
{
    virtual void abc() throw (exp1);
}

void base::abc() throw (exp1)
{
    ......
}

class sub : public base
{
    void abc() throw(exp1, exp2);
}

void sub::abc() throw (exp1, exp2)
{
    .....
}

13voto

Mike Seymour Points 130519

Le problème vient du fait que la sous-classe doit être utilisable partout où la classe de base peut être utilisée, et ne doit donc pas lancer d'autres types d'exceptions que celles spécifiées dans la classe de base.

Il existe trois solutions :

  1. Modifiez le spécificateur de la classe de base afin d'inclure tous les types d'exception qu'une sous-classe pourrait avoir besoin de lancer.
  2. Modifiez chaque sous-classe pour qu'elle gère tous les types d'exception, sauf ceux spécifiés dans la classe de base.
  3. Supprimez les spécificateurs d'exception.

Je suggère de les supprimer ; ils sont largement considérés comme une mauvaise idée, en partie à cause de problèmes comme celui-ci. Comme le souligne Matthieu, le comité de normalisation est d'accord et les spécificateurs d'exception seront dépréciés dans la prochaine version de la norme.

6voto

jrcalzada Points 206

Lorsque vous surchargez une méthode virtuelle avec un spécificateur throw dans une classe dérivée, la méthode de la classe dérivée ne peut pas lever plus d'exceptions que la méthode de la superclasse. Si vous étiez autorisé à le faire, vous pourriez rompre le contrat créé par l'API publique de la superclasse en surchargeant des méthodes dans une sous-classe.

Dans votre exemple, vous dites que base::abc peut seulement lancer exp1. Cependant, si vous avez un pointeur de type base qui pointe en réalité vers une instance de sub, tout d'un coup abc peut lancer exp2 en plus de exp1.

Pour résoudre le problème, vous devez supprimer exp2 du spécificateur throw de la sous-classe ou ajouter exp2 au spécificateur throw de la super-classe.

3voto

Jesse Beder Points 14026

Supposons que j'essaie

base *b = new sub;
b->abc();

Basé sur le spécificateur de lancement dans base::abc je m'attendrais à ce qu'il lance seulement exp1 mais sub::abc dit qu'il pourrait aussi jeter exp2 .

Si sub::abc peut vraiment jeter exp2 puis ajoutez exp2 à la liste de ce que base::abc peut lancer. Si ce n'est pas le cas, il faut le retirer de sub::abc de la liste de la Commission.

Et mieux encore : n'utilisez pas de spécificateurs de type "throw". Pour plus d'informations, voir Quelqu'un peut-il m'expliquer les spécifications des exceptions C++ ? y http://www.gotw.ca/publications/mill22.htm .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X