繁体   English   中英

在C ++中纠正异常

[英]Correct Exceptions in C++

我只是学习如何处理我的C ++代码中的错误。 我写了这个示例,查找一个名为some file的文本文件,如果找不到它将抛出异常。

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
int array[90];
try
{
   ifstream file;
   file.open("somefile.txt");
   if(!file.good())
    throw 56;
}
catch(int e)
{
    cout<<"Error number "<<e<<endl;
}
return 0;
}

现在我有两个问题。 首先,我想知道我是否正确使用了例外。 第二,(假设第一个是真的)使用它们对If else语句有什么好处?

“正确地”是一个值判断,但是(与其他类不同),异常类是一个单一的层次结构有一个主要的好处,所以我通常建议抛出从std::exception派生的东西, 不仅仅是一个int。

其次,可以肯定的是,不正确的文件名是否足够意外,无法作为抛出异常的理由。

至于利益与if / else声明:有一对。 首先,异常允许您隔离处理错误的代码,因此代码的主要思想和可读性不会在错误处理的迷宫中丢失。 其次,当你在抛出和捕获异常之间有几层代码时,抛出异常的代码可能不知道应该如何处理它。 例如,您的代码使用std::cout来报告问题 - 但大多数此类代码会报告std::cerr上的错误。 您可以从一个更改为另一个,而无需对尝试打开文件的代码进行任何更改(可能在库中很深,并且不知道哪个应该用于此应用程序 - 并且可能在应用程序中使用两者都错了,而MessageBox是首选)。

首先,我想知道我是否正确使用了例外。
是的,但通常您希望您的异常派生自std :: exception。

第二,(假设第一个是真的)使用它们对If else语句有什么好处?
对于给定的例子,没有。 当你拥有许多深层嵌套函数时,例外的好处就来了。

#include <stdexcept>
#include <iostream>
#include <string>

void anErrorFunc(const std::string& x)
{
    ifstream file;
    file.open(x);
    if (!file)
        throw std::runtime_error("Could not open file");
}

void someOtherFunction(const std::string& y)
{
    //Do stuff
    anErrorFunc(y);
    //Do other stuff
}

int main()
{
    try {
        someOtherFunction("somefile.txt");
    } catch (std::exception &ex) {
        std::cout << "Ouch! That hurts, because: "
            << ex.what() << "!\n";
    }
}

请注意,异常将在main()捕获,而someOtherFunction不必担心处理传递失败返回代码。

好吧,您正确使用异常,因为您的代码没有任何问题。 也就是说,通常我们不会抛出原始类型(即使你可以)。 抛出一个派生自std :: exception的对象通常更好一点,甚至更好地抛出一个同样是boost :: exception的std :: exception

当事情非常简单并且处理代码和抛出代码在同一个函数中时,实际上没有理由使用异常而不是if语句(事实上,如果......使用它会更快更有效率)否则在那个特殊情况下)。 但是,在大多数情况下,发现错误并且需要报告错误的点远离要处理错误的逻辑。 在许多情况下,错误恢复逻辑特定于所讨论的应用程序,并且发现错误的逻辑无法做出关于如何从错误中恢复的明智选择,因此需要抛出。

异常处理的另一个好处是异常的类型可用于传达发生的错误类型。 通常,异常层次结构中的类型比最终在C代码中使用的那些错误代码更有意义。 此外,您不能轻易忽略异常,因为您可以忽略错误代码; 虽然你可以忽略一个例外,它会导致程序死于可怕的死亡。 相比之下,如果C函数返回错误状态代码,并且您忽略它,则可以继续执行并获得静默错误的结果......从这个意义上说,使用异常比使用错误代码更安全。

您可能还有兴趣阅读C ++ FAQ Lite中的异常和错误处理

您没有正确使用异常。 您的代码具有更简单的等价物,没有例外,它提供相同的行为。

例外情况是指您无法使用其他方法测试函数调用的结果。 在这种情况下你可以,所以你不应该使用例外。

作为必然结果,你不应该在同一个函数体中抛出并捕获异常 - 只需做你想做的事情而不是抛出它。

从语法上讲,您的代码是正确的。 习惯上说,也许不是那么多 - 或者至少这取决于背景。 当一个文件无法打开时,我们可能会在那里进行处理if( !file.good() )如果它是完全常见的并且可能发生。 例如,如果用户要求在文本编辑器中打开文件,那么该文件不存在就完全合理且常见。 另一方面,如果编辑器找不到拼写语料库文件,那么这意味着(可以说)非常错误。 该程序可能没有安装,或者用户弄乱了该文件 - 一切皆有可能。

在C ++中,我们对异常情况使用异常。 也就是说,这些案件实际上并非意味着发生,而且我们并不“接受”这种情况。 这与用户文件未打开,无效用户输入或无互联网连接相反:这些都是完全有效的事情发生的例子,常见情况,我们期望在程序运行中迟早发生的事情。 它们并非例外

现在,与条件相比,使用异常有什么好处? 请允许我将此问题扩展到任何其他跳转( goto )机制:返回以及条件。 如果您想说的话,例外情况会更具表现力:如果您正在处理特殊情况,则使用例外。 异常也比普通条件更多地完成,其方式类似于虚函数比条件更多的完成。 正确的代码块将根据异常执行,但正确的范围将根据处理程序处理异常。

与条件相比,异常还有其他优点:异常将错误处理与其他代码分开。 它们允许将任意数据和操作与错误状态相关联。 它们允许通信成功状态(通过return )以及错误状态(通过throw )。 而这样的例子不胜枚举...

从技术上讲,在最低级别,异常是一种复杂的跳跃机制。 回到蝴蝶日,人们发明了if条件作为一个有点复杂的goto ,以增强表达力(因为goto可以用于任何真正的东西)并减少程序员错误。 诸如C for循环之类的循环结构本质上也是具有闪光和彩虹色的复杂跳跃,同样用于减少错误和增强表现力。 出于同样的原因,C ++引入了新的铸造运算符。

所以:异常不是魔术,只是与条件和循环相比,场景中有些新东西。 当你不打算使用时,不要使用它们,就像你真的想要使用条件时不使用循环一样。

从语法上讲,你所做的是正确的。 风格方面,正如其他人所指出的那样,你应该抛出std :: exception的后代。

关于你的问题的第二部分,我想详细介绍一下。

例外的全部内容是将政策与实施分开。 正如Billy ONeal所说,在if语句不能做得更好的同一函数中使用异常完全没有任何好处。 你需要在函数调用中深深嵌套它才有意义。

在大多数代码中,您的高级代码具有足够的信息和上下文来知道如何处理错误,但没有检测它们的机制。 您的低级代码可以检测到错误,但没有处理它们所需的信息。

应对此问题的传统方法 - 返回错误代码 - 存在一些问题:

  1. 它使用错误处理代码将代码混乱到实际逻辑被混淆的程度。
  2. 它依赖程序员不要懒惰并检查每个错误代码返回,这是一个经常是愚蠢的假设。 (C程序员,老实说:你最后一次检查printf的返回值是什么时候?)
  3. 它会将错误检查和处理的开销添加到每个函数调用中是否存在错误。

例外解决了这些问题(取得了不同程度的成功)。

  • 例外通过在检测点和处理点仅具有与异常相关的代码来解决#1。 干预功能不会因处理他们自己不感兴趣的晦涩错误而处理混乱,也不会处理。
  • 他们通过强制处理来解决#2问题。 你不能忽视一个例外。 你必须对它们采取行动。 (懒惰的程序员仍然可以捕获所有异常,然后忽略它们,但是现在突出显示他们对程序的无能为力了。)
  • 他们通过在不使用时具有接近零的成本来解决#3(当没有天真实施时),尽管在实际使用时通常成本非常高。

这并不是说异常是错误处理的最终/全部。 缺点:

  1. 使用时,例外情况通常非常昂贵。 如果表现至关重要,他们必须避开,尽管他们有优势。
  2. 异常有时会导致代码非常不透明。 它们是非本地控制转移 - 实际上是更安全的goto语句版本,但是跨功能。 一个例外可以在源代码文件中从代码深处的数百个层转移控制,甚至与您正在处理的文件略有关系(实际上,甚至很可能无法访问)。 这种“远距离的怪异行为”可能使代码很难弄明白。
  3. “经过例外”,实际上比旧式的是噪音产生更坏if处理。 你看,它们往往比ifswitch语句更加冗长,而且你必须处理代码的已检查异常以进行编译,这使得它们成为许多情况的责任。
  4. 由于它们的使用成本通常很高,因此不小心将它们用于所有错误处理会使代码变得缓慢而臃肿。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM