Vous semblez être pris au piège de quelqu'un qui essaie de manger son gâteau et de le manger.
La RAII et les exceptions sont conçues pour aller de pair. RAII est le moyen par lequel vous n'avez à écrire beaucoup de catch(...)
déclarations à faire le nettoyage. Cela se produira automatiquement, bien sûr. Et les exceptions sont le seul moyen de travailler avec des objets RAII, car les constructeurs ne peuvent que réussir ou lancer (ou placer l'objet dans un état d'erreur, mais qui le souhaite?).
Une catch
déclaration peut faire l’une des deux choses suivantes: gérer une erreur ou des circonstances exceptionnelles, ou effectuer des travaux de nettoyage. Parfois, il fait les deux, mais chaque catch
déclaration existe pour faire au moins une de celles-ci.
catch(...)
est incapable de gérer correctement les exceptions. Vous ne savez pas quelle est l'exception; vous ne pouvez pas obtenir d'informations sur l'exception. Vous n'avez absolument aucune information autre que le fait qu'une exception a été levée par quelque chose dans un certain bloc de code. La seule chose légitime que vous puissiez faire dans un tel blocage est de faire le ménage. Et cela signifie relancer l'exception à la fin du nettoyage.
Ce que RAII vous donne en ce qui concerne la gestion des exceptions est un nettoyage gratuit. Si tout est correctement encapsulé dans RAII, tout sera nettoyé correctement. Vous n'avez plus besoin que les catch
déclarations nettoient. Dans ce cas, il n'y a aucune raison d'écrire une catch(...)
déclaration.
Donc, je conviens que catch(...)
c'est surtout du mal ... provisoirement .
Cette disposition étant le bon usage de RAII. Parce que sans cela, vous devez pouvoir effectuer certains travaux de nettoyage. Il n'y a pas moyen de s'en sortir; vous devez être capable de faire le travail de nettoyage. Vous devez pouvoir vous assurer que le lancement d'une exception laissera le code dans un état raisonnable. Et catch(...)
est un outil essentiel pour le faire.
Tu ne peux pas en avoir un sans avoir l'autre. Vous ne pouvez pas dire que les deux RAII et catch(...)
sont mauvais. Vous avez besoin d'au moins un d'entre eux. sinon, vous n'êtes pas exceptionnellement en sécurité.
Bien sûr, il y a une utilisation valable, bien que rare, catch(...)
que même la RAII ne puisse bannir: la exception_ptr
transmission à quelqu'un d'autre. Généralement via une promise/future
interface ou similaire.
Mes collègues disent que vous devez toujours savoir quelles exceptions doivent être levées et que vous pouvez toujours utiliser des constructions telles que:
Votre collègue est un idiot (ou tout simplement terriblement ignorant). Cela devrait être immédiatement évident en raison de la quantité de code copier-coller qu'il suggère que vous écriviez. Le nettoyage de chacune de ces déclarations de capture sera exactement le même . C'est un cauchemar d'entretien, sans parler de la lisibilité.
En bref: c’est le problème que RAII a été créé pour résoudre (non pas qu’il ne résout pas d’autres problèmes).
Ce qui me déroute dans cette idée, c'est que c'est généralement à l'envers que la plupart des gens prétendent que RAII est mauvais. En général, l'argument est le suivant: "RAII est mauvais, car vous devez utiliser des exceptions pour signaler une défaillance du constructeur. Mais vous ne pouvez pas lancer d'exceptions, car ce n'est pas sûr et vous devez disposer de nombreuses catch
instructions pour tout nettoyer." Ce qui est un argument cassé parce que RAII résout le problème créé par le manque de RAII.
Plus que probablement, il est contre RAII parce qu'il cache des détails. Les appels de destructeurs ne sont pas immédiatement visibles sur les variables automatiques. Donc, vous obtenez un code qui est appelé implicitement. Certains programmeurs détestent vraiment ça. Apparemment, au point où ils pensent avoir 3 catch
déclarations qui font toutes la même chose avec du code copier-coller est une meilleure idée.
...
" alors que ma question se concentre sur "Dois-je mieux attraper...
ou<specific exception>
avant de retransmettre"