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

Cha*_*son 40 c c++ exception-handling

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

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

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

我发现这篇文章关于异常处理如何在幕后工作,但不确定该信息如何应用于我的问题(即,C缺乏通知,延续等?).提前致谢.

thi*_*ton 20

C不没有在机器代码,和异常处理是和是司空见惯用C与setjmplongjmp.

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

  • 在大多数C++编译器中处理异常处理的方式,其中成本是在throw端,无法使用setjmp和longjmp来模仿.特别是,即使没有抛出异常,调用setjmp也会在每个`try`块上强制成本.特别是GCC以昂贵的"抛出"为代价,基本上是零成本的"尝试".我不相信你可以在C语言级别复制这个. (7认同)
  • 我很好奇:C风格的例外如何处理清理中间分配?即使没有成熟的析构函数,也有人必须"释放"那个记忆,对吧?调用函数的唯一责任是确保分配不是"longjmp"吗? (2认同)
  • @Nicol:对于setjmp/longjmmp与所谓的"异常帧"的组合,您可以将异常视为"纯粹的语法糖".在C中,您可以创建每线程链接的结构列表.每当你持有一些需要释放的资源,并且想要调用可以"抛出"的东西时,你可以在列表中添加一个结构,调用该东西,然后取消链接结构.当某些东西"抛出"时,它会对列表末尾的任何内容进行"longjmps",并且该东西可以释放该级别的资源,然后将"longjmp"释放到列表中的下一个内容...... (2认同)
  • @ BlueRaja-DannyPflughoeft:在这一点上我们非常接近"结构化编程对于`goto`来说不是语法糖";-) (2认同)

Eri*_*ert 15

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

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

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

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

什么是C在机器代码中缺乏说,C++,使异常工作?

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

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

如果您对如何将异常处理添加到支持continuation的非OO语言的主题感兴趣,请参阅我的文章,该主题概述了这个想法:

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

  • @Doddy:JavaScript 的第一个版本是面向对象的,但没有异常处理。当我在 20 世纪 90 年代开始使用 C++ 编程时,我们使用的版本出于性能原因关闭了异常处理。Simula,第一个面向对象的语言,没有异常处理。 (2认同)

sbi*_*sbi 10

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

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

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

  • @Steve:GC只处理单一资源.它不会关闭您的文件,也不会释放您的互斥锁.AFAIK你必须使用`finally`明确地做到这一点.我认为这是C++的回归. (6认同)

ybu*_*ill 7

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

不,这两者是正交的.其他人提到setjmplongjmp用于C来处理错误.我想提到SEH.

SEH(结构化异常处理)是C的微软扩展,具有OS级别的支持.它允许您编写代码(例如来自MSDN):

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

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

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

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

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


BRP*_*ock 5

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

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