异常处理是否需要面向对象的编程?

时间:2011-12-20 18:00:45

标签: c++ c exception-handling

在我的编程经验的这一点上,我意识到我现在使用的大多数语言(C ++,。Net,Java等)都有异常处理,至少与C相比,我有多么糟糕。我准备好了参加高级C课程,让我真正想到这些术语与我目前的范例相比。

在C语言中,程序员应该首先防止错误发生,这对任何习惯于异常处理的人来说都是相当艰巨的。我发现任何遇到异常处理的语言都是面向对象的。至少据我所知,第一个面向异常处理的面向对象语言是C ++,它是C语言的演变。(如果我错了,请纠正我)

话虽如此,是否存在允许异常处理的语言的面向对象性质,或者是因为面向对象语言真正开始成为常见事件而添加的异常处理?什么是C在机器代码中缺乏说C ++,使得激活工作?

我发现这个post关于异常处理如何在幕后工作,但不确定该信息如何应用于我的问题(即,C是否缺少通知,延续等?) 。提前谢谢。

9 个答案:

答案 0 :(得分:20)

C在机器代码中没有任何内容,异常处理在C setjmplongjmp中很常见。

在纯过程语言中完全缺乏语言级功能的原因是,当不需要调用析构函数时,异常处理与setjmp相同。异常处理在外来语言中已经存在,但从未流行,因为它纯粹是语法糖。但是,一旦析构函数进入场景并且堆栈展开变得必要,语言级支持就变得必要了,异常处理作为语言的一部分被广泛实现。

答案 1 :(得分:15)

  

异常处理是否需要面向对象的编程?

没有。两者完全分开。可以将没有异常处理的OO语言作为控制流原语,并且可以在非OO语言中进行异常处理。

维基百科帮助指出,面向对象编程是一种强调抽象封装消息传递的价值的编程风格,模块化多态继承,以实现大型团队实施的复杂软件项目的低成本代码重用和有效管理

你没有在该列表中看到“循环”或“if语句”或“goto”或“try-catch-finally-throw”,因为控制流原语没有任何关系抽象,封装,消息传递,模块化,多态或继承被用于实现大型团队的低成本代码重用或复杂软件项目的有效管理。

  

在那些使异常有效的机器代码中,C缺少C ++的含义是什么?

当然,现代硬件的设计需要将异常处理作为控制流原语。 C在现代硬件存在之前设计很久,这使得在C中实现异常处理更加困难,C在所有运行C的硬件上高效运行。

但是说,没有什么能阻止你或其他任何人设计一个新版本的C,它将异常处理作为控制流原语,但没有C ++的所有其他功能。

如果您对如何向支持延续的非OO语言添加异常处理的主题感兴趣,请参阅我的文章,该主题草拟了这个想法:

http://blogs.msdn.com/b/ericlippert/archive/2010/10/22/continuation-passing-style-revisited-part-two-handwaving-about-control-flow.aspx

答案 2 :(得分:10)

  

话虽如此,是否存在允许异常处理的语言的面向对象特性,或者是因为面向对象语言真正开始成为常见事件而添加的异常处理?

当我在90年代初学习Ada(学习CS)时,我首先了解了例外情况。 IIRC,Ada有一种特殊类型Exception。那时候,它不是面向对象的语言。 (Ada95添加了一些OO概念。)但是,我同意堆栈展开(即完全自动清理已分配的资源)是异常处理成功的重要特征。将析构函数与异常处理相结合是C ++中异常成功的重要一点。

我似乎还记得Stroustrup提到Ada是C ++中异常处理的主要影响因素。

答案 3 :(得分:7)

  

异常处理是否需要面向对象的编程?

没有。两者是正交的。其他人提到了C中用来处理错误的setjmplongjmp。我想提到SEH。

SEH(结构化异常处理)是C的微软扩展,具有OS级别的支持。它允许您编写类似(example from MSDN)的代码:

__try 
{ 
    *pResult = dividend / divisor; 
} 
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ? 
         EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{ 
    // handle exception
}

您也可以通过拨打RaiseException来提出自己的例外情况。与setjmplongjmp不同,您可以在__finally块中进行自己的清理。事实上,C ++异常是在SEH(在Windows上)上实现的。

这是完全对象非定向方式的异常处理示例。

C ++中另一个不使用任何面向对象特性的例子:

try {
    throw "Boom!";
} catch(const char* str) {
    printf("Error: %s\n", str);
}

答案 4 :(得分:5)

实现异常处理的非面向对象语言包括:

  • ITS TECO
  • PL / 1(Multics)
  • C(有几个人已经指出,通过setjmp / longjmp
  • C通过Unix信号:Unix内核信号来自Multics异常处理设施
  • 旧版本的Lisp(已授予,Common Lisp允许OOP,但在添加条件和重新启动时没有添加)显然实现了条件并从ITS TECO重新启动(unwind-protect s) - 根据RMS(http ://www.gsim.aoyama.ac.jp/~ida/GNU/RMStalk1207.html),暗示Lisp实际上通过Emacs继承了异常处理(nifty!)

答案 5 :(得分:4)

对于非命令性示例,请尝试Haskell on size。甚至不需要将异常构建到语言中;它们只是返回类型的一部分(例如Either MyException MyValueExceptionalT IOException IO String)。可以使用try模块中的Control.Exception函数处理标准异常:

main = do
  result <- try (evaluate (1 `div` 0))
  case result of
    Left  exception -> putStrLn $ "Caught: " ++ show exception
    Right value     -> putStrLn $ "Result: " ++ show value

您还可以使用函数作为catch函数的异常处理程序,这里使用了中缀:

main = (print $ 1 `div` 0) `catch` \exception ->
  putStrLn $ "Caught: " ++ show exception

您可以使用Exception monad在另一个monad中执行异常抛出操作。通过处理所有可能的异常,您可以从Exception monad中逃脱。

main =
   do result <- runExceptionalT someFunction
      case result of
         Exception exception -> putStrLn ("Caught: " ++ show exception)
         Success   value     -> putStrLn ("Result: " ++ show value)

因为异常构成了函数类型签名的一部分,所以必须明确说明它。这与Java中的已检查异常基本相同。

答案 6 :(得分:1)

嗯,在汇编语言中可以找到异常,您可以使用陷阱(强制异常)和其他异常来控制程序流。一个例子是nullpointer或者为什么不是stackoverflow。没有任何关于OO语言的性质可以实现异常处理。它们只是让它变得更容易(而高级语言倾向于抛出更多例外)。例外是基本编程的一个关键特性。而且我并不是指所有的编程,我的意思是“常规”编程,包括汇编。当你说“C缺乏说C ++的机器代码使异常工作时,我不明白你的意思”。而且我不会说程序员完全可以在C中捕获异常(但我在这方面是新手。如果有人可以纠正我,请做。)

答案 7 :(得分:1)

在C ++之前,异常处理已经存在很长时间了。几种“精品”语言很早就实现了异常处理,但Ada(70年代后期,IIRC)可能是最知名的。 Ada有一些OO-ness的闪光,但不是任何现代标准的OO。

异常处理也在几个版本的PL / S语言(绝对不是OO)中实现,这些版本主要在IBM内部使用。早期的实现(可以追溯到70年代后期)是使用宏开发的(PS / S宏处理器在大多数情况下都优于大多数),但是后来的版本将EH嵌入到语言中。

答案 8 :(得分:1)

非OO语言也有例外,它是解开调用堆栈的有用抽象。示例包括ErlangForth