几个catch块或一个带dynamic_cast?

时间:2009-06-11 09:24:15

标签: c++ exception exception-handling

我们有一个异常类的层次结构 - 有一个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块不需要它。

哪个选项更好?可能是什么原因不是第一个选择?

4 个答案:

答案 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)

您需要虚拟功能来显示异常消息。此函数必须是根层次结构类的成员。