我们有一个异常类的层次结构 - 有一个GenericException
类和一些派生自它的类。 GenericException
是多态的 - 它有一个虚拟的析构函数。
在使用文件系统对象进行操作时,抛出了一个派生类FileException
来指示错误。 FileException
具有GetErrorCode()
方法,该方法返回指示实际出错的代码。
层次结构已经存在,我无法改变它,所以这是不可能的。
我们无法控制的代码抛出了异常,并且它们总是被 new 关键字抛出,因此我们只能通过指针捕获它们 - 这也是不可能的。
现在我遇到一种情况,一组语句可以生成一个异常,保证从GenericException
派生。如果它是FileException
和错误情况的类型是“找不到文件”我想什么都不做,否则我想显示错误消息然后我认为无论如何处理异常
我有两个选择 - 或者:
} catch( GenericException* e ) {
FileException* fileException = dynamic_cast<FileException*>( e );
if( fileException == 0 || fileException->GetErrorCode() != FileNotFound ) {
ShowMessage( e );
}
delete e;
}
或者这个:
} catch( FileException* e ) {
if( fileException->GetErrorCode() != FileNotFound ) {
ShowMessage( e );
}
delete e;
} catch( GenericException* e ) {
ShowMessage( e );
delete e;
}
我更喜欢第一个,因为它减少了代码重复。但我听说过,由于C ++允许选择性的catch块(比如第二个选项),我不应该使用dynamic_cast
- 选择性catch块不需要它。
哪个选项更好?可能是什么原因不是第一个选择?
答案 0 :(得分:4)
你永远不应该抛出指针。始终抛出值并通过const捕获 引用。永远不可能正确地清除动态分配的异常对象。
要回答你的问题,我个人不相信有复杂的例外情况。如果你需要对异常执行条件处理,你需要处理更接近throw网站的异常,在那里你有比你目前看起来更多的上下文信息。
答案 1 :(得分:3)
我更喜欢第二个。
如果您担心重复,您是否知道称为“异常调度程序”的内容?如果您发现需要执行相同catch处理的许多地方,可以将它们全部放在一个函数中,并从catch(...)块中调用此函数。
e.g。
void fn()
{
try
{
MightThrow();
}
catch (...)
{
ExceptionHandler();
}
}
void ExceptionHandler()
{
try
{
throw;
}
catch( FileException* e ) {
if( fileException->GetErrorCode() != FileNotFound ) {
ShowMessage( e );
}
delete e;
} catch( GenericException* e ) {
ShowMessage( e );
delete e;
}
}
它不会停止处理程序中的重复,但它会停止重复,你需要在不同的地方捕获相同的东西。
编辑:您必须确保在不处理异常时不会调用ExceptionHandler,否则会发生很多错误:related question
答案 2 :(得分:2)
如果用const&amp; amp;重写它,则第二个选项是“最佳”选项。 ;-)
我发现第二个比第一个更干净,它清楚地表明了你想要的东西。
答案 3 :(得分:0)
您需要虚拟功能来显示异常消息。此函数必须是根层次结构类的成员。