如何识别抛出的特定异常

Posted

技术标签:

【中文标题】如何识别抛出的特定异常【英文标题】:How to identify a specific exception thrown 【发布时间】:2014-07-01 20:37:57 【问题描述】:

我正在编写一个类来处理一个流,该流可以在它读取的数据中出现某些致命错误时引发多个异常(不是一次)。在该类的驱动程序中,我有一个 try/catch 块,我想在其中针对可能发生的特定不同异常执行不同的行为。

例如:

try
    functionWhichPerformsStreamProcessing(); // may throw exception at some point

catch (std::exception &exceptionWhichMustBeHandledDifferently)
    if ( <exception is some type> )
        <code to handle>
    
    else if ( <exception is some other type> )
        <different code>
    
    ...

我考虑过:

    检查异常的 .what() 字符串 如果字符串稍后更改,似乎很难调试 为每个异常子类化 std::exception 当需要为每个不同的异常创建一个新的子类时,这似乎有点矫枉过正 带有某种形式的错误代码的异常,可能是一个字符串,即使解释性 .what() 发生更改,它不会更改 我可能会在单独的标头中为这些标识符定义预处理器宏,以跟踪并确保它永远不会改变 不过,这让我想到了 C 风格的错误代码

Frame-based Exception Handling 可能是合适的,但它仅限于 Windows,我想让这段代码可移植,我实际上不知道它在说什么,所以它甚至可能不相关。

因为我正在处理一个流,如果发生这样的错误,我希望能够立即中断处理,所以我想在这里使用异常。可能有一些方法可以毫无例外地做到这一点,但目前的问题似乎很笼统,可以在其他地方使用,这就是我在这里问的原因。

对于这种情况有什么最佳做法吗?

【问题讨论】:

选项(2)是官方的做法。 使用子类化。我使用宏 DEFINE_EXCEPTION(exceptionName, what) 为非常简单的异常编写所有样板 【参考方案1】:

恕我直言,最好的方法是继承 std::exception。我通常会编写子类,除了我想快速摆脱的非常简单的异常。在这种情况下,我会使用宏..

但要获得有用的文本异常通常需要接受更多关于出错原因的上下文,这就是为什么最终大多数情况下它们是手写的。

这是我曾经使用过的一个例子:

#include <exception>

#define MAKE_EXCEPTION( v_class_name_, v_parent_name_, v_what_ )  \
 class v_class_name_                                              \
      : public  v_parent_name_                               \
      public:                                                 \
      inline virtual const char* what() const noexcept        \
             return v_what_;                        \
      


MAKE_EXCEPTION(ZipFileException, std::exception, "ZipFileException: General Failure in ZipFile Operation");

MAKE_EXCEPTION(ZipFileInvalidFileException, ZipFileException, "ZipFileInvalidFileException: File is not a zipfile. Or File is corrupt");

MAKE_EXCEPTION(ZipFileEncryptionNotSupportedException, ZipFileException, "ZipFileEncryptionNotSupportedException: Can't open encrypted zip files");

MAKE_EXCEPTION(ZipFileCompressionMethodNotSupportedException, ZipFileException, "ZipFileCompressionMethodNotSupportedException: Zip file contains a compression method that is not supported");

MAKE_EXCEPTION(ZipFileOpenException, ZipFileException, "ZipFileOpenException: Failed to open the zipfile");

MAKE_EXCEPTION(ZipFileMultiPartNotSupportedException, ZipFileException, "ZipFileMultiPartNotSupportedException: Can't open multipart zip files");

...

因此您只需一行代码即可获得异常,并轻松使用层次结构测试特定异常。

【讨论】:

这就是为什么最终大多数异常类都是手写而不是生成的。【参考方案2】:

如果您希望处理多个异常,您可以创建自己的异常子类化 std::exception,然后使用多个 catch 块构建一个 try-catch,如下所示:

try
    functionWhichPerformsStreamProcessing(); 

catch (yourExceptionType &differentExceptionWhichMustBeHandledDifferently)
    //do stuff

catch (yourAnotherExceptionTYpe &yetAnotherExceptionWhichMustBeHandledDifferently)
    //do some additional stuff

catch (std::exception &exceptionWhichMustBeHandledDifferently)
    //do some different stuff

它使您可以跳过所有这些 if-else 并使代码更清晰、更易于阅读。

【讨论】:

你应该把大多数派生放在第一位...不是吗?

以上是关于如何识别抛出的特定异常的主要内容,如果未能解决你的问题,请参考以下文章

如何识别 XCUITest 在 xcode 中运行时抛出的一些随机寡妇

忽略在 C# .NET 中抛出的特定异常

SQL 连接字符串在 C# 中无法识别并抛出异常

有效处理Java异常三原则

如何使用 Aspectj 捕获和抑制 Java 类抛出的异常

如何处理spring boot 2中@Requestbody中的对象抛出的异常