当前位置: 首页 > 科技观察

十点详解C++异常处理本文帮你全面剖析C++异常处理机制

时间:2023-03-17 16:52:26 科技观察

1.什么是异常处理?二、为什么需要异常,以及异常处理的基本思想C++之父BjarneStroustrup在《The C++ Programming Language》中说:一个库的作者可以检测到发生了运行时错误,但一般不知道如何去检测处理它们(因为用户应用程序特定);另一方面,库的用户知道如何处理这些错误,但无法检查它们何时发生(如果可以检测到,则可以在用户的??代码中处理,而不是留给库去发现)。BjarneStroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现一个它无法处理的错误时抛出(throw)一个异常,然后它的(直接或间接)调用者就可以处理这个问题。这就是《C++ primer》所说的:将问题检测与问题处理分开。一种思路:在所有支持异常处理的编程语言中,公认的一个思路:在异常处理过程中,问题检测代码可以抛出一个对象给问题处理代码,通过对象的类型和内容object,theactual两部分的通信就在上面完成了,通信的内容是“哪里出了问题”。当然,各种语言在异常的具体实现上或多或少存在差异,但是这种交流的思路是一致的。三、异常发生前的错误处理方式在C语言的世界里,错误的处理总是围绕着两种方式:一种是使用整型返回值来识别错误;另一种是使用errno宏(可以简单理解为一个全局整型变量)来记录错误。当然,这两个方法在C++中还是可以使用的。这两种方式最大的缺点就是会出现不一致的情况。例如,一些函数返回1表示成功,0表示错误;一些函数返回0表示成功,非零表示错误。另一个缺点是函数只有一个返回值。如果用函数的返回值来表示错误码,那么函数就不能返回其他值。当然你也可以通过指针或者C++引用来返回其他值,但这可能会让你的程序略显晦涩难懂。第四,为什么例外是好的。优点如下:1.函数的返回值可以忽略,但是异常不能忽略。如果程序中出现异常,但没有被捕获,程序就会终止,这多少会鼓励程序员开发更健壮的程序。但是,如果使用了C语言的错误宏或函数返回值,调用者可能会忘记检查,从而导致错误得不到处理,导致程序莫名终止或出现错误结果。2.整数返回值没有任何语义信息。异常包含语义信息,有时可以从类名中体现出来。3.整数返回值缺少相关的上下文信息。Exception,作为一个类,可以有自己的成员,而这些成员可以传递足够的信息。调用之间可以跳过异常处理。这是一个写代码的问题:假设有多个函数的调用栈发生错误,使用整型返回码需要你在函数的每一层都处理。但是利用异常处理的栈扩展机制,只需要在一处处理,而不需要逐层函数处理。五、C++中使用异常应该注意的问题任何事情都有两个方面,异常有优点也有缺点。如果在代码中使用了异常,需要注意以下几点:1.性能问题。这个一般不会成为瓶颈,但是如果你写的软件性能高或者实时性要求强,就需要考虑了。2、指针和动态分配引起的内存回收问题:动态内存不会自动回收。如果遇到异常,需要考虑内存是否被正确回收。函数抛出的异常列表:如果写noexcept,表示可以抛出任何异常。6.异常的基本语法很简单。Throwathrowandtry...catchthrow:当出现问题时,程序会抛出异常。catch:在你要处理问题的地方,通过异常处理程序捕获异常。try:try块中的代码标识将被激活的特定异常。它后面通常跟一个或多个catch块。noexcept:用于声明函数不抛出异常。如果函数抛出异常,则直接中断,无法捕获。try...catch语句的语法如下:try{//保护代码}catch(ExceptionNamee1){//catch块}catch(ExceptionNamee2){//catch块}catch(ExceptionNameeN){//catch块}如果try块在不同的情况下抛出不同的异常,此时可以尝试列出多个catch语句,使用捕获不同类型异常时的注意事项:catch的匹配过程是寻找第一个匹配,而不是最佳匹配。在catch的匹配过程中,对类型的要求比较严格。不允许标准算术转换和类类型的转换。(类类型转换包括两种类型:通过构造函数进行隐式类型转换和通过转换运算符进行类型转换)。七、异常栈解捻异常抛出后,从进入try块到异常抛出之前,这段时间在栈上构造的所有对象都会被自动销毁。破坏顺序与构造顺序相反。这个过程称为堆栈的展开。structMaker{Maker(){cout<<"Maker()构造函数"<#includeusingnamespacestd;//第一类Out_Range:publicexception{public:explicitOut_Range(conststring&_Message):exception(_Message.c_str()){}explicitOut_Range(constchar*_Message):exception(_Message){}};//第二种structExce:publicexception{constchar*what()constoverride{return"Exce";}};voidfoo(intarr[],intlen){inti=-1;if(i<0||i>=len){throwOut_Range("数组越界~");}cout<