何时捕获异常?

Posted

技术标签:

【中文标题】何时捕获异常?【英文标题】:When to catch exceptions? 【发布时间】:2010-11-05 10:30:07 【问题描述】:

如果我在不使用异常的情况下执行以下操作会有什么不同吗?

void func()

    try
    
        if (n > 5)
        
            throw "n is greater than 5";
        
    
    catch (const char *e)
    
        MessageBox(0, e, 0, 0);
        return;
    

void func()

    if (n > 5)
    
       MessageBox(0, "n is greater than 5", "Error", 0);
       return;
    

【问题讨论】:

你会因为在第一种情况下抛出 char const* 而被丢弃。 标题“错误”和对代码进行逆向工程可能有所不同。 . . 【参考方案1】:

我可能会说你最好不要使用异常来控制流。 Exceptions,顾名思义,就是用来处理特殊情况的。在上述情况下,您显然希望 n 可能 > 5,因此这并不是一个特殊情况。如果您的应用程序有办法处理这种情况,那么它应该优先处理这种情况,而不是引发异常。

我确信在某些情况下这种逻辑会失败,但总的来说,我认为这是一个很好的经验法则。

但在技术方面并没有太大区别(如果你经常这样做,可能会表现出性能)。

【讨论】:

【参考方案2】:

永远不要抛出你在同一个函数中捕获的异常。这表明您正在使用标准控制流的异常,最好使用 if/while/break/etc。

【讨论】:

@Alf:通常你永远不应该说永远。这是一个例外! :) 好的,那么,关于在同一个基于异常的函数中抛出和捕获异常的规则的异常的一个异常是,当您在 C++ 中模拟类似于 Java 异常的 finally 时。虽然 RAII 通常会更干净,但我猜可能会有一些例外?干杯,【参考方案3】:

最终结果将是完全相同的,这是肯定的。

您应该尽量简化代码,因此我强烈反对在这种情况下使用异常。

【讨论】:

【参考方案4】:

很难确切地说何时应该使用异常。在某些情况下,例外是明显的赢家,而在其他情况下则不是。

问题的核心是n是从哪里来的,在正常情况下是否可以是> 5的值。如果n是由函数本身计算的,并且正常可以有这个值,那么异常不会'感觉不对。但是,如果在其他地方指定了 n,并且此函数只是不期望很高的值,那么异常感觉更正确。

但是,我会说您的示例是对异常的错误使用。在同一个函数中抛出和捕获异常几乎总是不好的形式。这是标准流量控制。当错误条件需要传播到函数之外时,应使用异常。

【讨论】:

【参考方案5】:

在您的示例中没有真正的区别(除了一个使用异常而另一个不使用的明显事实!) - 这将是一个合理的重构。但是,如果有很多不同的错误条件,您可能会发现 throw... catch 模式可以帮助您将错误处理集中在一个地方。

【讨论】:

【参考方案6】:
void func()

    if (n > 5)
    
       MessageBox(0, "n is greater than 5", "Error", 0);
       return;
    

不要自己抛出异常,如果你可以通过上面代码的检查自己处理它,它不是一个好习惯。

【讨论】:

【参考方案7】:

在您的示例中,没有区别。您唯一需要弄清楚的是,当抛出异常时,在 try...catch 方法中找到的其余语句将永远不会被执行。 Exceptions 基本上用于处理“改变程序正常执行流程的特殊情况”。 (您的只是基本的正常逻辑错误流)。

希望这会有所帮助。

【讨论】:

【参考方案8】:

你没有定义n

n 的以下定义存在不同的可观察行为:

struct Silly

    ~Silly()  cout << "Hm de dum" << endl; 
    operator bool() const  return true; 
;

struct SillyProducer

    Silly operator>( int ) const  return Silly(); 
;

#define n   Silly silly = SillyProducer()

干杯,

【讨论】:

【参考方案9】:

已经说了很多,我就补充一点吧。

在您的情况下,这两种情况都是正确的,但我鼓励将其分为两层:逻辑和视图。所以你的逻辑层会这样做:

    doLogic()
    
      if (n > 5)
      
         throw "n is greater than 5";
      
      ///Something more
    

您的视图层可能会这样做:

try
 
   doLogic()

catch (const char *e)

    MessageBox(0, e, 0, 0);
    return;

但是,正如其他人所说:最重要的是 n 来自哪里。如果您希望它超过 5,那么只需使用 if() else,而不是异常。但如果 n 总是小于 5,并且大于 5 意味着您的系统有问题,则使用异常。

【讨论】:

以上是关于何时捕获异常?的主要内容,如果未能解决你的问题,请参考以下文章

python 这意味着无论何时引发未捕获的异常,我都会立即得知发生了什么(完全回溯)。

Sonarqube - 避免捕获通用异常

在 C++ 中通过指针捕获异常

Android捕获崩溃异常

在catch块中捕获异常后,是否可以再次在try块中执行代码?

前端捕获异常技巧总结