您似乎陷入的困境是某人试图吃蛋糕也要吃蛋糕的特定地狱。
RAII和例外的设计是相辅相成的。RAII是你没有的手段都写了很多的catch(...)
语句做清理工作。当然,它会自动发生。异常是使用RAII对象的唯一方法,因为构造函数只能成功或抛出(或将对象置于错误状态,但是谁想要呢?)。
一catch
言可以做两件事情之一:处理错误或特殊情况,或做清理工作。有时它会同时执行这两个操作,但是每个catch
语句都存在至少执行其中一个操作的条件。
catch(...)
无法执行适当的异常处理。您不知道例外是什么。您无法获取有关异常的信息。除了一个事实是某个代码块内的某个东西引发了异常之外,您绝对没有其他信息。在这种情况下,您唯一可以做的合法事情就是进行清理。这意味着在清理结束时重新抛出异常。
RAII在异常处理方面为您提供的是免费清理。如果一切都被RAII正确封装,那么一切将被正确清理。您不再需要让catch
语句进行清理。在这种情况下,没有理由编写catch(...)
语句。
因此,我同意这catch(...)
主要是邪恶的…… 暂时。
该规定是RAII的正确使用。因为没有它,您需要能够进行某些清理。没有解决的办法。您必须能够进行清理工作。您需要确保抛出异常将使代码处于合理状态。并且catch(...)
是这样做的重要工具。
你不能没有一个。您不能说RAII 和 catch(...)
都不好。您至少需要其中之一;否则,您也不例外。
当然,catch(...)
即使RAII都无法消除它的一种有效-尽管很少使用的方法:将其exception_ptr
转发给其他人。通常通过一个promise/future
或类似的界面。
我的同事说,您应该始终知道要抛出哪些异常,并且始终可以使用类似以下的构造:
您的同事是个白痴(或者非常无知)。由于他建议您编写多少复制和粘贴代码,因此这应该立即显而易见。每个catch语句的清理将完全相同。那是维护的噩梦,更不用说可读性了。
简而言之:这是创建 RAII 来解决的问题(不是说它不能解决其他问题)。
使我感到困惑的是,这通常被大多数人认为RAII不好的观点所落后。通常,该论据是:“ RAII不好,因为您必须使用异常来表示构造函数故障。但是您不能抛出异常,因为它不安全,并且您将不得不使用大量catch
语句来清理所有内容。” 这是一个有争议的论点,因为RAII 解决了RAII缺乏造成的问题。
他极有可能反对RAII,因为它隐藏了细节。析构函数调用在自动变量上不立即可见。这样您就可以隐式调用代码。一些程序员真的很讨厌。显然,至于他们认为拥有3条catch
语句,所有这些语句都使用复制和粘贴代码执行相同的操作是一个更好的主意。
...
”的问题,而我的问题集中在“我应该更好地抓住...
还是<specific exception>