8
votes

Pourquoi essayer ... Catch nécessite un type exact lancé

Je peux le faire, pas de problème: xxx

mais si j'essaie ceci: xxx

Je reçois une exception non gérée. < / p>

Cela semble incompatible. Quelle est la raison de la conversion de type dans ce cas?


13 commentaires

Écrivez 100 fois: "Je n'aurai que des objets qui dérivent de STD :: Exception"


@Taadeusz sauf avec l'idiome commun de lancer un int pour terminer un programme. ( principal contient un essayer ... Catch pour attraper le int et le renvoyer. Cet idiome a le même effet que l'appelant , sauf que les destructeurs de toutes les variables locales sont appelés.)


@Jameskanze: Intéressant, je ne savais pas à propos de cet idiome. J'ai vu un suicideexception qui hérité de rien, une fois, je vais deviner le rôle. Dans les deux cas, bien que vous ne soyez vraiment pas sur le fait que personne n'a jamais écrit une clause (...) .


@Jameskanze: J'ai entendu parler de cet idiome, mais je ne pense pas que ce soit commun. Quelle serait une situation où vous voulez une sortie à moitié immédiate? Si vous ne pouvez pas gérer une exception, ne l'attrapez pas. Et si vous le pouvez, eh bien, attrapez-le.


@phresnel Je ne sais pas que l'idiome est ce courant, bien que je l'utilise souvent moi-même. Il est un cas valide où on lancerait un int , cependant. (Sur le seul à laquelle je puisse penser, de dire la vérité.)


@Matthieu Évidemment, vous comptez sur le fait que personne ne absorbe simplement toutes les exceptions. (Un attrape (...) n'est pas un problème si il retire.) Pratiquement, je ne peux pas penser à un cas où on voudrait ignorer complètement tout exceptions.


@Jameskanze: Je ne peux pas la comprendre non plus, mais je l'ai vu :(


@Jameskanze: Mais c'est ce cas valable que vous mentionnez?


@phresnel lancer un int afin de mettre fin à un programme. C'est l'exception à la règle que tout ce que vous lancez devrait dériver de std :: exception .


@Jameskanze: Comment vais-je dire ... Je ne comprends pas pourquoi il devrait être bon de "quitter immédiatement" un programme du tout. Lire: Je ne connais pas une seule raison pour laquelle lancer est justifié dans tous les cas. J'ai eu que vous parlez de se terminer comme ça, mais pourquoi une cérémonie devrait-elle se terminer comme ça? C'était ma question. Je comprends que vous pouvez utiliser lancer si vous souhaitez la variante Clean C ++ de EXIT . Mais je ne comprends pas pourquoi vous devriez en avoir besoin. En cas d'erreur, jetez quelque chose approprié, puis attrapez ou non. Si vous souhaitez retour , juste retour . Et parce que ce n'est pas courant, cela confondra ppl.


@Jameskanze: Et si vous avez besoin de cela pour sortir de la grande hiérarchie, je suppose que jette est simplement une aide à la bande pour une hiérarchie et un flux de contrôle cassé.


@phresnel, il s'appelle une erreur fatale. Il y a des erreurs (ne pas programmer des erreurs telles que des défaillances d'affirmation, mais des conditions extérieures) qui signifient que le programme ne peut pas continuer, ni qu'il n'a aucun sens pour qu'il continue.


@James Kanze: Je vois, bien qu'il reste encore le danger que les ressources non-Raii ne soient pas libérées. Je ne suis pas d'accord sur ne pas utiliser les ressources RAII, mais ils font partie de nombreux projets.


5 Réponses :


0
votes

Vous pouvez attraper plusieurs types dans un bloc d'essai. Pour que le compilateur sache quel bloc de capture à jeter, il doit être capable de faire correspondre le type exact. Ou il peut avoir un bloc de capture par défaut - attraper (...) {} , mais vous ne pourrez pas obtenir à la valeur lancée dans ce cas.


0 commentaires

1
votes

La déclaration de capture attrape un objet (ou une variable scalaire dans vos cas) donnée son type, de sorte que si le type inadéquation, il passe à la relevé de capture suivante (s'il en existe un) ou au récepteur d'exception par défaut.

Dans votre cas, vous pourriez avoir une deuxième déclaration de capture capturée de long, et peut-être ailleurs, alors votre déclaration de capture n'attrapera rien.

Attirer une exception, il suffit d'utiliser Catch () {} :)

Un seul conseil, meilleure utilisation de la classe d'exception ou la sous-classement pour vous avoir besoin de besoin :)


0 commentaires

8
votes

Dans le premier cas, le compilateur peut dire exactement ce que vous voulez faire: Convertissez un long code> à un int code>. Dans le second cas, le compilateur doit supposer que vous pourriez avoir une construction comme celle-ci:

try {
  try {
    throw 3L;
  }
  catch (int i) { /* P */ }
}
catch (long l) { /* Q */ }


0 commentaires

1
votes

Vous pouvez également lancer 3; - aucun problème.

int et long sont différents types. C'est un avantage de la manipulation des exceptions que vous pouvez raconter les exceptions en dehors de la recherche de leur type (un bloc d'essai central peut gérer des exceptions de différents types de divers endroits / un bloc d'essai peut gérer à d'autres types d'exceptions, laissant ainsi les autres propager).

En outre, il est recommandé de lancer une des exceptions standard ou de dériver une classe d'une de ces personnes. Ensuite, vous pouvez simplement CATCH (CONST STD :: EXCEPTION &) Si vous souhaitez simplement gérer l'exception et ne vous souciez pas du type particulier.


0 commentaires

4
votes

attrape code> ne em> pas em> nécessite nécessairement le type exact.

Il est courant et pratique d'utiliser des exceptions dérivées de std :: exception code > (trouvé dans code>). La raison en est que vous pouvez ensuite attraper polymorphiquement, c'est-à-dire que vous faites pas em> besoin de connaître le type exact (voir aussi Différence: STD :: runtime_error vs std :: Exception (exception () ) Et que nous avons une convention pour gérer cela. p>

soit que vous utilisez. L'une des celles fournies par la norme (par exemple, std :: plongez_error code>), ou si rien ne convient à vos problèmes [suffisamment], Spécialiser std :: Exception code>: P>

oh oh: moores law stopped. duck under your table.


0 commentaires