为什么C ++允许抛出任何东西?

时间:2018-12-05 10:12:02

标签: c++ exception-handling

我刚刚看到this question及其相关答案。 考虑到我以前从未遇到过使用throw的这种方式,我很惊讶地发现这甚至是可能的。

  • 允许(几乎)扔掉和抓住任何东西背后的逻辑是什么?
  • 是否使用了异常/错误信号以外的throw-catch语法?如果是这样,是被认为是不好的做法还是我从未意识到的“通用”用法?

5 个答案:

答案 0 :(得分:3)

1。。您可以抛出任何内容,因为C ++并未像Java或C#那样定义特定类的目的。在这种语言中,您只能抛出从其指定的异常类继承的类的对象。 C ++没有the one异常类(没人强迫您使用std-stuff)。

2。。使用throw / catch发出非错误消息的信号称为异常驱动开发,确实被认为是不好的做法。异常驱动的开发导致难以理解的代码。这也可能导致代码段不会被无意执行。我强烈反对这样做。

答案 1 :(得分:3)

不作推测就很难回答,但是Bjarne在1998年的论文"An Overview of the C++ Programming Language"中描述异常处理时使用了任意类型,并建议为方便/语义创建一个上述类型的层次结构。似乎一开始他就没有想到exception的“基类”。

具有标准层次结构(基于std::exception)的概念有可能作为“加法”开始生活,这是接近Bjarne建议的异常使用的便捷方法,而不是每个人的构建基石。异常的使用应基于。当代的做法是从std::exception派生所有例外,似乎以后会出现。

如今,我想不出一个很好的理由不这样做,除非出于其他原因,除了那些使用您的代码的人可能会期望顶级catch (const std::exception&)吸收任何有用的东西。我也倾向于将catch (...)放在main中,以防万一。

更实际地说,如果不是这种情况,则必须有其他规则约束throw才对从std::exception派生的类型的表达式“有效”具有足以证明附加规则合理的任何现实利益。不管您信不信,C ++源自一个极简主义的问题:“为什么我们没有这样的规则?”,尽管显然它的膨胀似乎与此矛盾。这些年来。

我怀疑这与将throw用于非例外情况有关,因为这一直被认为是不良做法。 Bjarne描述此功能的方式是:

  

异常用于将控制权从检测到错误的位置转移到对处理此类错误表现出兴趣的某些调用方。显然,这是仅应用于无法在本地处理的错误的机制。 [..]异常可用于使错误处理更加规范和常规。

因此很明显,至少最初的设计意图(同样,这仍然是常识)是仅将异常用于异常/错误情况。

答案 2 :(得分:2)

  

输入处理程序后,e将是在Int_overflow对象内部创建的副本。   添加功能来描述出了什么问题。   现在与函数调用的并行几乎是精确的:throw-expression传递Int_overflow   声明为接受类Int_overflow的对象的处理程序的object。通常的初始化语义   用于传递此参数。抛出的对象的类型用于大致选择处理程序   函数调用的参数用于选择重载函数的方式。再次,略   查看throw-expression的另一种方式是作为return语句,其中参数不仅是   传递回呼叫者,但也用于选择要返回的呼叫者。
  [...]
  依靠这种基本且得到良好支持的语言概念,而不是发明一些   特殊的“例外类型”可确保使用C ++的全部功能来定义和使用例外。

Exception Handling for C++”,安德鲁·科尼格(Andrew Koenig),比雅妮·史都鲁普(Bjarne Stroustrup),1989年

这可能会回答您有关该行为背后逻辑的问题。 C ++的创建者希望使用现有技术来实现新功能。

关于您对该功能的合理使用的疑问,我将再次引用同一出版物的内容:

  

我们不希望使用异常处理来代替   更常规的控制结构

我留待您和其他评论者来决定是否更多的现代实践可能超越了发明人的最初想法。

答案 3 :(得分:1)

C ++的一般哲学是允许程序员做他们想做的任何事情(并发动自己的脚),大多数限制只是为了实现可移植性而已,甚至某些限制不是某些编译器所强制执行的。 / p>

如果您不需要创建std::exception对象的开销(确实很小),C ++不会强迫您为此付费。例如,您可能直接抛出错误代码,这比使用错误代码成员创建std::exception的子类要容易得多。当然,您的代码调用者需要知道期望捕获不是std::exception子类的数字。出于这个原因,通常最好只抛出std::exception的子类,但不必。

答案 4 :(得分:0)

我不是Bjarne Stroustrup,但我会尝试给出答案。

  

允许(几乎)扔掉和抓住任何东西背后的逻辑是什么?

惯例是从标准库中抛出std::exception的派生词。如果您限制可以抛出的内容,则只能使用它。 C ++试图: 1.给您很大的灵活性 2.管理已经很复杂的语言 通过让语言抛出并捕获任何东西,您将为程序员提供灵活性。通过将std::exception移至标准库,而不是将其作为语言本身的一部分,也使该语言的复杂性降低。

  

是否使用了异常/错误信号以外的throw-catch语法?

是的,您可以使用它来传递信号。这是不明智的反模式(滥用)。