English 中文(简体)
为什么应该保守地利用例外?
原标题:Why should exceptions be used conservatively?

我经常看到/有人说,例外情况只应很少使用,而永远不能解释原因。 虽然情况可能确实如此,但理由通常是一种平衡:it 称为例外,理由”,对我来说,这似乎是一种解释,永远不应被尊敬的方案管理员/工程师接受。

有一些问题可以用来解决。 Why 是不明智地将其用于控制流动? 什么哲学依据是特别保守的? 杂质 业绩? 复杂性? Aesthetics? 公约:

我看到了以前对业绩的一些分析,但程度与某些系统有关,与其它系统无关。

同样,我不一定不同意在特殊情况下应当予以挽救,但我不怀疑协商一致的理由是什么(如果存在这种理由)。

问题回答

主要的摩擦点是杂质。 许多开发商滥用例外规定,并抓住一切机会。 想法是将例外情况用于某些特殊情况。 例如,错误用户的投入并不算作例外,因为你预计会发生这种情况并准备就绪。 但是,如果你试图创建档案,而且磁盘上的空间还不够,那么,这是肯定的例外。

另外一个问题是,例外往往被抛弃和吞.。 研制者利用这一技术简单地“保持”方案,让它尽可能长地运行,直至完全崩溃。 这是错误的。 如果你没有处理例外情况,如果你没有通过释放某些资源来适当作出反应,如果你没有记录例外的发生,或至少没有通知用户,那么你就不再使用例外手段。

直接回答你的问题。 很少采用例外做法,因为例外情况很少,例外情形昂贵。

拉雷,因为你并不期望你在每顿报上或每台消息灵常的用户投入上坠毁节目。 Say,数据库可能突然无法使用,软磁盘上的空间可能不够,某些第三方服务你依赖的电离线,这种情况可能发生,但很少会发生。

支出,因为放弃例外将中断正常方案流动。 运行时间将缩短,直到找到能够处理例外情况的适当例外手。 它还将收集通话信息,并将通过一切方式传递给手将接收的例外情况。 所有这一切都有代价。

这并不是说,使用例外(里程)没有任何例外。 有时,如果你放弃一个例外,而不是通过许多层次提出回归法,那么它就可以简化法典结构。 作为一项简单规则,如果你期望某种方法常常被称作,发现某些“例外”的情况是时间的一半,那么找到另一种解决办法是更好的。 然而,如果你预计大部分时间会正常运转,而这种“例外”的情况只能在某些罕见的情况下出现,那么放弃例外只是罚款。

@Comments: 在某些不太例外的情况下,如果能够使你的法典更加简单和更容易地使用例外,这种例外肯定会得到使用。 这一选择是开放的,但我可以说,在实践中是很罕见的。

为什么不明智地使用它们来控制流动?

由于例外情况扰乱了正常的“控制流动”。 你提出例外,方案正常执行可能被放弃,有可能使物体处于不连贯状态,一些公开资源得不到释放。 Sure, C#有使用声明确保即使从使用机关提取一个例外处理物体。 但让我们从语言中抽取。 支撑这个框架为你们赢得了物。 你是人工操作的。 你们有一些要求和释放资源和记忆的制度。 你们有全系统的协议,负责在什么情况下释放物品和资源。 你们有如何处理外部图书馆的规则。 如果方案遵循正常运行流程,它就会发挥巨大作用。 但是,在处决中,你突然提出一项例外。 一半资源没有获得。 半数尚未提出要求。 如果行动意在交易,现在就中断。 你处理资源的规则不会奏效,因为那些负责释放资源的法典部分仅仅赢得了执行。 如果其他人想要利用这些资源,他们也会发现这些资源不符合规定,而且因为无法预测这一具体情况。

因此,你希望采用M(a)电话方法N()做一些工作,并安排一些资源,然后返回M(M)使用,然后处置。 罚款。 现在,N(a)的情况是错误的,它给你在M(a)的 t意留下了一种例外,因此,在它可能陷入某种C(C)方法之中之前,例外情形就显得格外重要,因为这种方法对N(a)中正在发生的事情以及是否和如何释放某些资源没有任何想法。

除提出例外情况外,你还设法将你的方案纳入许多难以预测的新中间邦,这些国家难以预测、理解和处理。 它与使用GOTO有点相似之处。 很难设计一个能够任意从一个地点跳到另一个地点的方案。 这样做也是难以维持的。 当方案日益复杂时,你会失去对什么时候和什么地方来加以缩小的概述。

虽然“特别谣言中的排位例外”是折衷的答案,但你可以实际界定这些情形:满足前提条件,但不能满足条件。 这使你能够在不牺牲错误处理的情况下写出更严格、更紧凑、更有用的先决条件;否则,除例外情况外,你必须改变定点,使每一个可能的错误状态成为可能。

  • Preconditions must be true before calling a function.
  • Postcondition is what the function guarantees after it returns.
  • Exception safety states how exceptions affect the internal consistency of a function or data structure, and often deal with behavior passed in from outside (e.g. functor, ctor of a template parameter, etc.).

Constructors

各位几乎无法就每一类建筑商说什么,这些建筑商可能在C++上写,但有一些东西。 其中最主要的是,将拆除已建物体(即施工者成功归还的物体)。 青年不能修改这一先决条件,因为语言假定是真实的,并且将自动叫脱轨者。 (在技术上,您可以接受以下几种语言规定的不明确行为的可能性:no则保证anything,,但可能最好在别处加以涵盖。)

当建筑商不能成功时,放弃例外的唯一选择是修改该类的基本定义(“等级”),以便允许有效的“null”或zombie邦,从而允许建筑商通过建造omb子而“被教育”。

Zombie example

“zombie”修改的一个例子是st:ifstream,在你能够使用之前,你必须始终检查国家。 由于std:string,例如,t.,总是保证在施工后立即使用。 如果你必须写成像这样的法典,如果你想阻止omb子邦,你要么无声地取得不正确的结果,要么 corrupt倒你方案的其他部分:

string s = "abc";
if (s.memory_allocation_succeeded()) {
  do_something_with(s); // etc.
}

即使指明这一方法,也就是一个很好的例子,说明你必须如何改变这一类别,并改变现状的接口string,既不能预测也不能处理。

Validating input example

请举一个共同的例子:验证用户的投入。 仅仅因为我们希望允许不成功的投入,就意味着parsing function需要将这种投入纳入其先决条件。 这确实意味着如果教区失败,我们的手必须检查。

// boost::lexical_cast<int>() is the parsing function here
void show_square() {
  using namespace std;
  assert(cin); // precondition for show_square()
  cout << "Enter a number: ";
  string line;
  if (!getline(cin, line)) { // EOF on cin
    // error handling omitted, that EOF will not be reached is considered
    // part of the precondition for this function for the sake of example
    //
    // note: the below Python version throws an EOFError from raw_input
    //  in this case, and handling this situation is the only difference
    //  between the two
  }
  int n;
  try {
    n = boost::lexical_cast<int>(line);
    // lexical_cast returns an int
    // if line == "abc", it obviously cannot meet that postcondition
  }
  catch (boost::bad_lexical_cast&) {
    cout << "I can t do that, Dave.
";
    return;
  }
  cout << n * n <<  
 ;
}

不幸的是,这显示了两个例子,即C++的复印要求你打破RAII/SBRM。 在沙尔的一个例子中,没有问题,我希望C++能够做些什么——尝试:

# int() is the parsing "function" here
def show_square():
  line = raw_input("Enter a number: ") # same precondition as above
  # however, here raw_input will throw an exception instead of us
  # using assert
  try:
    n = int(line)
  except ValueError:
    print "I can t do that, Dave."
  else:
    print n * n

Preconditions

预设条件无需严格检查——违反规则的情况总是表明有逻辑的失败,而且这是叫人的责任——但如果你检查,那么就应当提出例外。 (在某些情况下,返回停车场或坠毁方案更为合适;尽管这些行动在其他情况下可能非常错误。) 如何最好地处理

具体来说,与std:logic_errorstd:runtime_error中分级分级分级分级。 前者经常被用于违反先决条件行为,后者则更适合违反先决条件的行为。

  1. Expensive
    kernel calls (or other system API invocations) to manage kernel (system) signal interfaces
  2. Hard to analyze
    Many of the problems of the goto statement apply to exceptions. They jump over potentially large amounts of code often in multiple routines and source files. This is not always apparent from reading the intermediate source code. (It is in Java.)
  3. Not always anticipated by intermediate code
    The code that gets jumped over may or may not have been written with the possibility of an exception exit in mind. If originally so written, it may not have been maintained with that in mind. Think: memory leaks, file descriptor leaks, socket leaks, who knows?
  4. Maintenance complications
    It s harder to maintain code that jumps around processing exceptions.

一项例外在某种程度上类似于 go。 这是为了控制流动,最后是采用不可理解的传教法。 更糟糕的是,在某些情况下,你甚至不知道跳跃到哪里(即,如果你在特定情况下没有达到例外)。 这公然违反了加强可维持性的“最意外”原则。

例外情况使得更难以解释贵国方案的状况。 例如,在C++中,你必须做额外思考,以确保你的职能非常安全,如果他们确实需要的话,就不必这样做。

原因是,除例外情况外,一项职能要求要么可以返回,要么可以首先终止方案。 除例外情况外,一项职能呼吁可以返回,也可以终止方案,或者可以跳跃到某个地方。 因此,你不能再跟随控制的流动,就在你们面前看着守则。 你们需要知道所要求的职能能否消失。 你们也许需要知道什么东西可以被抛弃,什么地方被 caught住,取决于你们是否在控制地进行照料,或者只看看它留下了目前的范围。

因此,除非情况是真实的,否则“人民”、“人民”、“......”、“......”、“......”、“......”、“......”、“......”。 当你到场时,“releases”是指“ < > > > ...... ...... ...... ...... 收益与收益值相抵后,则由>费用所抵消。 因此,这一说法是空话,尽管你在“......”、“......”、“......”、“......”、“......”、“......”、“......”、“......”、“......”、“......”。 当人民获得控制时,他们会获得回报价值的利益。

Java的定义比C++更为宽泛。 C++方案制定者比 Java方案管理员更可能想看功能的回报价值,因此,在 Java,“非常例外”可能意味着“由于这一功能,我可以不退回非核物体”。 在C++中,这更可能意味着“我非常怀疑我的助手能够继续工作”。 因此,如果能够读到档案, Java流就会消失,而C++(违约)流回的价值则显示错误。 无论如何,这是你愿意迫使你的打电话者必须写字的问题。 因此,这确实是一个交错的风格问题:你们必须达成共识,你们的法典应当看什么,以及你想写多少“核查”的法典,来反对你想要做的“例外安全”理由。

各种语文的广泛共识似乎是,在错误可能恢复方面做得最好(因为无法弥补的错误不会造成除例外情况外的代码,但仍然需要使用错误回报的代码中带有检查和回归的机)。 因此,人们期望“我称之为一种例外”,即“<>I能够继续”,而不仅仅是“<>t 不能继续”。 这并非例外所固有的,它只是一种习俗,而与任何良好的方案拟定做法一样,是聪明的人所倡导的一种习俗,他们以其他方式尝试,却得不到结果。 我的经历也好坏,造成太多的例外。 因此,我个人确实想到的是“非常例外”,除非有关情况的某些内容特别令人信服。

以前,除了对你的法典状况进行解释外,还涉及业绩。 例外通常在现在便宜,其语言是你有权照顾业绩。 它们可能比“谁,结果会产生错误,我最好也出错,然后”。 在恶劣的老日里,确实有人担心,放弃一种例外,追赶它,接着做些事情,就会使你所干的事情变得如此缓慢,无法无用。 因此,在这种情况下,“非常例外”意味着“局势非常糟糕,可怕的表现不再发生”。 这种情况已经不再存在(尽管在紧凑的路口中仍有例外),希望能说明为什么“非常例外”的定义需要灵活。

确实没有共识。 整个问题有些主观,因为放弃例外的“适当性”常常是由语言本身的标准图书馆中的现有做法提出的。 C++标准图书馆的例外情况比 say标准图书馆少很多,而后者几乎always更倾向于例外,甚至包括预期错误,如用户投入无效(例如Scanner.next)。 Int 。 我认为,这大大影响人们对于何时可以提出例外的看法。

作为C++方案管理员,我个人倾向于保留非常“例外”的例外情况,例如从记忆中、在磁盘空间外、发生突发事件等等。 但我并不坚持认为,这是做事的绝对正确方式。

我认为,很少使用例外。 但是。

并非所有小组和项目都准备使用例外情况。 采用例外规定,需要高度限定方案制定者、特殊技术,以及缺乏大量遗留的非特例安全法。 如果你拥有庞大的旧法典基础,那么几乎总是不是例外。 我确信,你不想重写。

如果你将广泛使用例外情况,那么:

  • be prepared to teach your people about what exception safety is
  • you should not use raw memory management
  • use RAII extensively

另一方面,在有强大团队的新项目中采用例外做法,可能会使守则更清洁、更容易维护甚至更快捷:

  • you will not miss or ignore errors
  • you haven t to write that checks of return codes, without actually knowing what to do with wrong code at low-level
  • when you are forced to write exception-safe code, it becomes more structured

<EDIT 11/20/2009:

我刚刚读到:

放弃例外的履约成本是巨大的。 虽然有条理的例外处理是处理错误条件的建议方式,但确保只有在出现错误情况时,才可使用例外情况。 不使用常规控制流动的例外情况。

当然,这只针对网络,还特别针对那些发展高性能应用(如我一样)的人,因此显然不是普遍真理。 然而,我们有很多。 该网络开发商们出那里,因此我认为值得注意。

www.un.org/Depts/DGACM/index_spanish.htm

首先,请简单一点: 我无意就业绩问题与任何人进行斗争。 事实上,事实上,我倾向于同意那些认为过早优化是一种罪.祸首的人。 然而,请允许我谈两点:

  1. 海报要求以传统智慧为根据提出客观理由,即应当少地利用例外。 我们可以讨论可读性和适当设计我们所希望的一切;但这些都是主观问题,人们愿意在任何一方争辩。 我认为该海报知道这一点。 事实是,利用例外情况来控制方案流动常常是做事的低效方法。 页: 1 因此,它提出合理建议,很少使用例外情况,就像它提供吃红肉或喝酒的好建议一样。

  2. 毫无理由地优化和撰写高效守则之间存在差异。 由此得出的结果是,撰写有力、如果不是优化的话,与简单无效率的东西之间存在差异。 有时,我想当有人对诸如例外处理之类的事情进行争辩时,他们确实只是相互谈论,因为他们正在讨论根本不同的问题。

为了说明我的观点,考虑了以下C#代码实例。

Example 1: Detecting invalid user input

这是我称之为例外的例子:abuse

int value = -1;
string input = GetInput();
bool inputChecksOut = false;

while (!inputChecksOut) {
    try {
        value = int.Parse(input);
        inputChecksOut = true;

    } catch (FormatException) {
        input = GetInput();
    }
}

对我来说,这部法典是荒谬的。 当然,它work。 没有人对此提出异议。 但should 例如:

int value = -1;
string input = GetInput();

while (!int.TryParse(input, out value)) {
    input = GetInput();
}

Example 2: Checking for the existence of a file

我认为,这一设想实际上非常普遍。 它肯定是/em>,对许多人来说,更多的是“可接受的”,因为它涉及I/O:

string text = null;
string path = GetInput();
bool inputChecksOut = false;

while (!inputChecksOut) {
    try {
        using (FileStream fs = new FileStream(path, FileMode.Open)) {
            using (StreamReader sr = new StreamReader(fs)) {
                text = sr.ReadToEnd();
            }
        }

        inputChecksOut = true;

    } catch (FileNotFoundException) {
        path = GetInput();
    }
}

这似乎有足够的道理? 我们再次试图开立档案;如果它没有的话,我们就抓住了这一例外,并试图开立不同的档案。 这有什么错误?

确实没有。 但认为这一替代方案doesn t。 放弃任何例外:

string text = null;
string path = GetInput();

while (!File.Exists(path)) path = GetInput();

using (FileStream fs = new FileStream(path, FileMode.Open)) {
    using (StreamReader sr = new StreamReader(fs)) {
        text = sr.ReadToEnd();
    }
}

当然,如果这两个办法的实际表现是一样的,这确实是一个理论问题。 因此,请看一下。 第一个守则实例是,我提出了10 000个随机扼杀清单,其中没有一个是适当的分类,然后添加了有效的分类。 采用上述两种办法,是我的结果:

Using try/catch block: 25.455 seconds
Using int.TryParse: 1.637 milliseconds

第二种情况是,我基本上采取了同样的做法:提出了10 000个随机扼杀清单,其中没有一个是一条有效的途径,然后又增加了一条有效的道路。 结果是:

Using try/catch block: 29.989 seconds
Using File.Exists: 22.820 milliseconds

许多人会对此做出回应,说“Yeah,好,扔下10 000个例外情况,是极其不现实的;这夸大了结果”。 当然,这是这样做的。 对用户来说,将一个例外处理与处理不正确投入之间的差别并不明显。 事实仍然是,在这两种情况下,使用例外情形比同样可读的其他办法,从1 000到10 000倍以上”。

因此,我列举了以下<代码>GetNine(方法>的例子。 ∗∗∗∗ 速度缓慢或<>可接受>的速度缓慢;其速度比should<>>>>> ...... 免费<>

同样,这只是两个例子。 在<>系列>中,使用例外情形的表现有时不是这种严重的情况(Pavel s权利;毕竟,它取决于执行情况)。 所有我说的话都是:在像上述情况一样的情况下,让我们面对事实、ys, throw弃和捕获一种例外,类似于;它只是一种低效的做事方式,很容易做更好的


你们要求说明这样的理由,即如果这是每个人在没有知情的情况下跳上波段的情况之一。 但事实上,答案是显而易见的,我认为你已经知道。 <>外观处理具有可喜的业绩

“K”可能因为你特别的商业情况而被罚款,但 相对而言,<>> ......> 放弃/扣押一项例外规定,在很多情况下,其管理费用会超过必要。 你们知道,我知道:大部分时间<>,如果你在控制方案流动方面再次使用例外规定,你只读写缓慢的代码。

你们也许会问:这一法典为什么不正确?

private int GetNine() {
    for (int i = 0; i < 10; i++) {
        if (i == 9) return i;
    }
}

我很幸运的是,如果你介绍这一职能,你就会发现它非常迅速地执行你典型的业务申请。 这并没有改变这样的事实,即它为完成能够做得更好的东西,提供了极其低效的方法。

这是人们在谈论例外时所说的意思。

关于例外的所有umb规则都是主观的。 你们不期望在何时使用和何时不使用这些定义时,会得到硬性和迅速的定义。 “只在例外情况下”。 尼斯循环定义:例外情况。

当使用例外情形时,与“我是否知道该守则是一类还是二类”一样。 它部分是一个次要问题,部分是偏好。 例外是一种工具。 它们可以加以利用和滥用,确定两者之间的界线是方案拟订的艺术和技能的一部分。

有许多观点和权衡。 找到与你交谈的内容,然后做。

不应当很少使用例外。 这只是说,他们只能在特殊情况下被抛弃。 例如,如果用户进入错误密码,这并非例外。

原因很简单:例外情形突然退出功能,并将之传播到<条码>> 副渔获物/代码>栏。 这一过程在计算上非常昂贵:C++建立其例外制度,在“正常”职能要求上几乎没有间接费用,因此,在提出例外情形时,它必须做很多工作来寻找出路。 此外,由于每一条法典可能产生例外。 如果我们有某些职能<条码>f,经常提出例外情况,我们现在必须注意使用我们的<条码><>/条码>。 页: 1 这对交错/执行造成混淆。

我处理错误的方法是,有三种根本错误:

  • An odd situation that can be handled at the error site. This might be if a user inputs an invalid input at a command line prompt. The correct behavior is simply to complain to the user and loop in this case. Another situation might be a divide-by-zero. These situations aren t really error situations, and are usually caused by faulty input.
  • A situation like the previous kind, but one that can t be handled at the error site. For instance, if you have a function that takes a filename and parses the file with that name, it might not be able to open the file. In this case, it can t deal with the error. This is when exceptions shine. Rather than use the C approach (return an invalid value as a flag and set a global error variable to indicate the problem), the code can instead throw an exception. The calling code will then be able to deal with the exception - for instance to prompt the user for another filename.
  • A situation that Should Not Happen. This is when a class invariant is violated, or a function receives an invalid paramter or the like. This indicates a logic failure within the code. Depending on the level of failure, an exception may be appropriate, or forcing immediate termination may be preferable (as assert does). Generally, these situations indicate that something has broken somewhere in the code, and you effectively cannot trust anything else to be correct - there may be rampant memory corruption. Your ship is sinking, get off.

简言之,如果你有问题,可以例外处理,但你可以在你通知的地方处理。 你们不能处理的问题只能是杀害方案;你能够处理权利问题,应该简单地处理。

I read some of the answers here. I m still amazed on what all this confusion is about. I strongly disagree with all this exceptions==spagetty code. With confusion I mean, that there are people, which don t appreciate C++ exception handling. I m not certain how I learned about C++ exception handling -- but I understood the implications within minutes. This was around 1996 and I was using the borland C++ compiler for OS/2. I never had a problem to decide, when to use exceptions. I usually wrap fallible do-undo actions into C++ classes. Such do-undo actions include:

  • creating/destroying a system handle (for files, memory maps, WIN32 GUI handles, sockets, and so on)
  • setting/unsetting handlers
  • allocating/deallocating memory
  • claiming/releasing a mutex
  • incrementing/decrementing a reference count
  • showing/hiding a window

Than there are functional wrappers. To wrap system calls (which do not fall into the former category) into C++. E.g. read/write from/to a file. If something fails, an exception will be thrown, which contains full information about the error.

随之而来的例外情况是,在失败后增加更多的信息。

Overall C++ exception handling leads to more clean code. The amount of code is drasticly reduced. Finally one can use a constructor to allocate fallible resources and still maintain a corruption free environment after such a failure.

One can chain such classes into complex classes. Once a constructor of some member/base object is exectued, one can rely on that all other constructors of the same object (executed before) executed successfully.

与传统建筑相比,例外是一种非常罕见的流动控制方法(流动、租赁、功能等)。 正常控制流动结构(流动、功能要求等)能够处理所有正常情况。 如果你发现自己是例行发生的例外情况,那么你或许需要考虑一下贵国的法典的结构。

但是,某些类型的错误无法与正常建筑一起轻易处理。 低水平可检测到中世纪的失败(如资源分配失败),但可能无法处理,因此,如果说不适当,简单不过。 这些类型的失败一般需要以高得多的级别处理(例如,除案卷外、记录错误、空档)。 试图通过传统方法(如回归价值)报告类似错误是荒谬的,容易发生错误。 此外,它还将间接费用注入中层的抗灾能力,以应付这一荒谬的异常故障。 间接费用分散了这些软件的客户,要求他们担心自己无法控制的问题。 例外情况为非当地处理大差错提供了一种途径,这些大差错在发现问题与该问题的手持之间最为看不见。

如果客户打电话ParseInt,并附上插图,则直接打电话者可能注意错误,并知道如何做。 因此,你设计了ParseInt,以换取类似的东西。

另一方面,如果是<代码> ParseInt之所以失败,是因为它无法分配缓冲,因为记忆非常分散,因此打电话的人没有了解这方面的情况。 这种异常的错误将不得不加以掩饰,并可能影响到处理这些根本失败的一些层面。 这对每个人征税(因为他们不得不在自己的APIC中考虑到错误通过机制)。 一种例外情况是,可以绕过这些层次(尽管仍然确保进行必要的清理)。

当你重写低层次的法典时,很难决定何时使用传统方法,何时放弃例外。 低级法典必须作出决定(增长或无)。 但是,这部高层次的法典确实知道什么是预期的,什么是例外。

C++有若干原因。

首先,它经常难以看到有例外情形(因为它们几乎可以被抛在一边),因此,从COME发言中可以发现捕获块。 这比一项目标更糟,因为在一项目标中,你知道你从哪里(发言,而不是一些随机的传说)以及你回去(标签)。 它们基本上是一种潜在的资源安全模式,即C s setjmp()和长jmp(),任何人都不想使用。

第二,C++确实有垃圾收集,因此,C++级拥有资源,在他们的骑手里拿走。 因此,在C++例外处理系统中,必须管理范围上的所有反应堆。 用GC语言,没有真正的建筑商,如Java,将例外搁置起来远比累。

第三,C++社区,包括Bjarne Stroustrup和标准委员会以及各种汇编作者,一直认为例外应当是例外。 总的来说,这不利于语言文化。 执行所依据的假设是,例外情况很少。 较好的书籍将例外情况作为例外处理。 良好的源代码使用少数例外。 良好的C++开发商将例外情况作为例外处理。 反之,你想有一个好的理由,我看到的所有理由都是为了保持这些例外。

这是一种使用例外作为控制流动的坏例子:

int getTotalIncome(int incomeType) {
   int totalIncome= 0;
   try {
      totalIncome= calculateIncomeAsTypeA();
   } catch (IncorrectIncomeTypeException& e) {
      totalIncome= calculateIncomeAsTypeB();
   }

   return totalIncome;
}

情况非常糟糕,但应当写:

int getTotalIncome(int incomeType) {
   int totalIncome= 0;
   if (incomeType == A) {
      totalIncome= calculateIncomeAsTypeA();
   } else if (incomeType == B) {
      totalIncome= calculateIncomeAsTypeB();
   }
   return totalIncome;
}

第二个例子显然需要一些调整(如采用设计模式战略),但充分表明,例外情况并非控制流动。

例外情况还涉及一些业绩处罚,但业绩问题应当遵循以下规则:“最佳地位是所有邪恶的根源”。

  1. Maintainability: As mentioned by people above, throwing exceptions at a drop of a hat is akin to using gotos.
  2. Interoperability: You can t interface C++ libraries with C/Python modules (atleast not easily) if you are using exceptions.
  3. Performance degradation: RTTI is used to actually find the type of the exception which imposes additional overhead. Thus exceptions are not suitable for handling commonly occurring use cases(user entered int instead of string etc).

我要说的是,例外情况是一种机制,使你摆脱目前的情况(从最简单意义上讲,现在的 st脚,但比这更加安全)。 结构最严密的方案拟订工作必须去做。 为了以打算使用例外的方式使用这些例外情况,你不得不在你现在能够继续做些什么的情况下这样做,而且你现在可以不处理。 因此,例如,当用户口号错误时,你可以继续找回假。 但是,如果国际调查小组的子系统报告说,它甚至能够促使用户使用,那么仅仅退回“log失败”就是错误的。 目前的法典水平根本不知道需要做什么。 因此,它利用一种例外机制,将责任交给上述可能知道要做的事情的人。

我倾向于尽可能少使用例外。 例外规定,开发商必须处理可能或可能不会产生实际错误的某些条件。 有关例外是否是一个致命问题或一个问题应立即处理。

反面的争辩是,仅仅要求 la人打上自己的脚。

谷歌编码政策说到,无论使用何种例外情况,特别是在C++。 您的申请或是准备处理例外情况,或是准备处理例外。 如果是 t,那么该例外可能会蔓延到你的申请死去为止。

发现一些图书馆,你利用这些图书馆提供例外,而且你没有准备处理。

提出例外的合法案件:

  • You try to open a file, it s not there, a FileNotFoundException is thrown;

非法案件:

  • You want to do something only if a file doesn t exist, you try to open the file, and then add some code to the catch block.

我在希望时使用例外情况,即申请的流至某一点。 这一点就是这一例外的捕获量(......)。 例如,我们处理项目负荷非常常见,每个项目都应独立于其他项目处理。 因此,项目处理过程的漏洞有试捕区,如果项目处理过程中出现一些例外,该项目的所有内容都会回落,错误被拖拉,下一个项目也得到处理。 生活继续。

我认为,你应当对像一个没有档案、一个无效的表述和类似的 st子这样的东西作例外处理。

RecordIterator<MyObject> ri = createRecordIterator();
try {
   MyObject myobject = ri.next();
} catch(NoSuchElement exception) {
   // Object doesn t exist, will create it
}

这将更好:

RecordIterator<MyObject> ri = createRecordIterator();
if (ri.hasNext()) {
   // It exists! 
   MyObject myobject = ri.next();
} else {
   // Object doesn t exist, will create it
}

www.un.org/Depts/DGACM/index_spanish.htm COMMENT ADDED to the ANSWER:

也许我的榜样非常好——在第二个例子中,Rri.next()不应成为一种例外,如果是的话,就应当采取某种非常例外的做法,并且应当采取其他一些行动。 当例1被大量使用时,开发商将捕获一个通用的例外,而不是具体例外,并假设该例外是因为它们所期望的错误所致,但也可能是其他原因造成的。 最终,由于例外成为申请流动的一部分,而不是例外,这导致了真正的例外被忽略。

这方面的评论可能比我的回答多。

基本上,例外是没有结构的,难以理解流动控制的形式。 在处理不属于正常方案流动范围的错误条件时,这样做是必要的,以避免出现错误处理逻辑,使你的代码的正常流动控制过多。

当打电话者忽视书写错误处理代码时,或者如果该错误可能比直接打电话者更进一步处理时,应当使用IMHO例外。 停电是用合理的诊断错误信息退出方案。 惯用的替代办法是,该方案在错误状态和坠毁或默默默无闻的状态下行不通,在较后更难以诊断。 如果“error”方案流动的正常部分足以使打电话者无法合理地加以检查,那么就不应使用例外。

我认为,“很少使用”不是正确的句子。 我倾向于“只有在例外情况下才行”。

许多人解释说,为什么不在正常情况下使用例外。 例外情况有权处理错误和纯粹处理错误。

我将重点讨论另一个问题:

另一个问题是业绩问题。 竞争者花了很长的时间才能迅速获得。 我不肯定,现在的确切状态如何,但在你使用控制流动的例外情况时,会遇到其他麻烦: 你们的方案将变得缓慢!

原因是,例外不仅非常容易夸张,而且必须减少他们离开的所有框架。 因此,从表面上讲,必须拆除 st的物体,等等。 因此,不了解这种情况,一只一只一小块 exception子就会真正涉及一整座机械师。 加工商必须做大量的工作。

因此,你将最终放弃,不知情地焚烧你的加工商。

因此,只在例外情况下使用例外情形—— 计算: 当出现实际错误时!

例外情况的目的是使软件故障具有容忍性。 然而,必须针对某一职能所放弃的每一项例外做出反应,导致镇压。 例外只是一种正式结构,迫使方案者承认某些事情可能与例行公事相差,客户方案者需要了解这些条件并视需要满足这些条件。

简言之,例外是方案拟定语文中增加的一个词汇,为开发商提供一些正式要求,将处理错误案件的责任从直接开发商转移到一些未来的开发商。

我认为,正如我们在C++和 Java中所知道的那样,良好的方案拟订语言并不支持例外情况。 你们应选择能够提供各种功能返回价值的替代流动的方案语言。 如果我能够这样做,方案管理员应负责预测例行工作的所有形式产出,并在适当的法典档案中处理这些产出。

如果:

  • an error occured that cannot be recovered from locally AND
  • if the error is not recovered from the program should terminate.

如果能够从(用户进入“pple”,而不是数)中收回错误,那么(对投入进行反复分析,对违约值进行改动等)。

如果无法从当地收回错误,但申请可以继续(用户试图开立档案但档案不存在),那么错误代码是适当的。

如果无法从当地收回这一错误,而且如果不恢复,申请就不能继续(青年不在记忆/空间/地点),那么,一个例外是正确的途径。

Who said they should be used conservatively ? Just never use exceptions for flow control and thats it. And who cares about the cost of exception when it already thrown ?

我的两点:

我想使用例外,因为允许我像没有发生错误那样进行方案。 因此,我的法典仍然可以读懂,并非分散于各种错误处理。 当然,错误处理(例外处理)被移至尾端(捕获区),或被视为电离层的应负。

我的一个很好的例子就是档案处理或数据库处理。 假设一切照样,最后或如果出现某种例外,就关闭你的档案。 或者在出现例外情况时收回交易。

除例外情况外,问题在于它很快会变得非常好。 虽然这是为了使你的法典能够保持非常可读性,而且只是注重正常的物品流动,但如果使用几乎始终如一的每项功能,则需要在一个尝试/渔获体内加以包装,并着手打败这一目的。

页: 1 如前所述,与例外的概念一样。 只是回报价值。 如果参数不能平坦,则会成为一个例外。 这一方面使你的法典更加干净。 在呼吁方面,你需要做这样的事情。

try 
{
   b = ParseInt(some_read_string);
} 
catch (ParseIntException &e)
{
   // use some default value instead
   b = 0;
}

该法典是干净的。 当像ParseInt一样分散起来时,即履行处理例外和归还我违约值的总结职能。 E.g.

int ParseIntWithDefault(String stringToConvert, int default_value=0)
{
   int result = default_value;
   try
   {
     result = ParseInt(stringToConvert);
   }
   catch (ParseIntException &e) {}

   return result;
}

因此,最后一点是,讨论忽略了的是,例外使我能够更容易/更容易读懂,因为我可以更无视错误条件。 问题:

  • the exceptions still need to be handled somewhere. Extra problem: c++ does not have the syntax that allows it to specify which exceptions a function might throw (like java does). So the calling level is not aware which exceptions might need to be handled.
  • sometimes code can get very verbose, if every function needs to be wrapped in a try/catch block. But sometimes this still makes sense.

因此,有时很难找到良好的平衡。

I m sorry, but the response is “they are known freedoms for aêt?” 这一解释是“th权”。 您不能给出一整套情况,即例外应当或不应使用,因为一个问题领域(英文定义)的致命例外是不同的问题领域正常的操作程序。 没有盲目遵循umb。 相反,它们旨在指导你对解决办法的调查。 “出于某种原因,这些例外被称作例外”告诉你,你应当提前确定打电话者能够处理哪些是正常错误,以及打电话者在没有特殊编码(副渔获物区)的情况下无法处理哪些异常情况。

就每个方案拟订规则而言,的确是一条准则,“除非你有真正良好的理由,否则不要这样做”: “无论怎样使用””、“避免全球变数”、“在逐个增加你的问题数目之前的用语”等。 例外并非例外。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?