C++中的异常机制

            **C++中的异常机制**

常用的函数

include< cstdlib >头文件中几个异常处理函数:
abort()//程序直接退出,打印一些消息;
exit(1)//接受一个参数,程序直接退出;

异常处理机制:

异常提供了将控制权从程序的一部分传递到另一部分的途径,对异常的处理有三个部分组成:
引发异常—————->>由关键字throw抛出
使用处理程序捕获异常—————–>>catch关键字捕获异常并进行处理
使用try块—————>>标识特定的异常可能被激活的代码块,后面可跟多个catch块。(注意try后面一定要跟catch块,如果try块和catch块后面有其他语句编译会报错)
例如要计算两个数的除法,如果除数为0就会引发异常,请看如下代码:

include<iostream>
double hmean(double a,double b);
int main()
{
    double x,y,z;

    std::cout<< "Enter two number:\n";
    while(std::cin >> x>> y)
    {
        try
        {
            z=hmean(x,y);
        }
        catch (const char *s)
        {
            std::cout << s <<std::endl;
            std::cout<< "Enter a new number: ";
            continue;
        }
        std::cout<< "Harmonic mean of " << x << "and" << y<< "is " << z << std::endl;
        std::cout << "Enter next set of number <q to quit>:";
    }
    std::cout << "Bye!\n";
    return 0;
}
double hmean (double a,double b)
{
    if(b==0)
    throw "b=0 not allowed";
    return a/b;
}

执行结果:C++中的异常机制_第1张图片

在本程序中程序先执行完try块中的程序,如果没有引发任何异常,则程序直接跳过try块后面的catch块,执行catch块后面的第一条语句,如果try块中的函数,当b=0;时throw将抛出异常,catch语句将对其进行处理
如果函数z=hmean(x,y);没在try块内,而是在try块外面调用,将无法处理异常,当异常出现时,程序会自动调用abort()函数

如果都没有try块和catch块时,在默认情况下,程序最终调用abort()函数;

异常的规范:

异常规范————>>是否有必要仍存争议;
作用:
1、告诉用户可能需要使用try块———————>>使用注释便可轻松完成
2、让编译器添加执行运行阶段检查的代码,检查是否违反异常规范————>>很难做到(异常产生很难预测)
基于上述的两个原因C++11摒弃了C++98增加的这一项功能。
但是C++11支持一种特殊的异常规范:使用关键字noexcept来指出函数不会引发异常;
double mam() noexcept;//表示该函数不会引发异常。
关键字noexcept 出了用于指出函数不会引发异常外,它也可以用作运算符,判断操作数、表达式是否会引发异常,操作数可能引发返回false,否则返回true。
Throw—catch机制和函数返回机制的不同:
1、 函数中的返回语句将控制权返回到调用的函数,而throw语句将控制权向上返回到第一个能够捕获相应异常的try—catch组合的函数。
2、 引发异常时编译器总是创建一个临时拷贝,即使异常规范和catch块中指定的是引用。

类的异常:

由于基类引用可以 执行派生类对象,如果有一组通过继承关联起来的异常类型,则在异常规范中只需列出一个基类引用,它将与任何派生类对象相匹配。因此,基类引用能够捕获任何异常对象;而派生类对象只能捕获它所属的类及这个类所派生出来的类的对象,而引发的异常对象将被第一个与之匹配的catch块所捕获。所以catch块的排列顺序应该与派生顺序相反。

class bad_1
{......};
class bad_2: public bad_1
{......};
class bad_3 : public bad_2
{........};

void fun()
{
    if(exp1)
    throw bad_1();
    if(exp2)
    throw bad_2();
    if(exp3)
    throw bad_3();
}
try
{
    fun();
}
catch(bad_3& ha)
{.......}
catch(bad_2& ha)
{.......}
catch(bad_1& ha)//基类放到最后 
{.......}

提示:如果有一个异常类继承的层次结构,应这样排列catch块:将捕获位于层次结构最下面的异常类的catch语句放在最前面,将捕获基类异常的catch语句放到最后面

不知道会发生什么异常时,使用省略号来表示异常类型,从而捕获任何异常。

catch(…)
{
//statements
}

异常何时会迷失方向

异常一种是意外异常:在异常规范的函数中引发的,必须与规范列表中的某种异常相匹配,默认情况下将导致程序异常终止。
另外一种:未捕获异常:没有在函数中引发(函数没有异常规范),并且也没有将其捕获,默认情况下这将导致程序异常结束。

为什么出现异常时会导致程序结束?
发生异常时时异常不会导致程序立刻异常终止,如果是未捕获异常,程序将首先调用函数terminate()在默认情况下terminate()函数将调用abor()函数。如果发生意外异常时,程序将调用unexpected()函数,这个函数将调用terminate()函数,后者将默认调用abort()函数,所以程序会异常结束。

如何让程序出现异常时不异常终止呢?
对于未捕获异常:可以指定terminate()应调用的函数(而不是abort()),来修改terminate()这种行为,因此可以调用set_terminate()函数,此时需要添加头文件exception;
Set_terminate()函数将接受一个不带任何参数且返回类型为void的函数指针作为参数:
具体做法:

include<cstdlib>
using namespace std; 
void fun()
{
    cout << "hahahahahahahahahahaha";
    exit(1);
}
Int main()
{
set_terminate(fun);
……………………//接上述程序,不过try块的函数放到try外面,设置为未捕获异常
}

执行结果:
(http://img.blog.csdn.net/20150516150139241)

如果不加set_terminate(fun); dev—cpp编译器执行结果为:
(http://img.blog.csdn.net/20150516150125743)
如果发生意外异常:
还在琢磨,望大神赐教,不胜感激。

你可能感兴趣的:(catch,try,throw,异常机制)