异常:程序在运行过程中发生的异常情况的一种响应,如被0除。
Abort()函数位于头文件cstdlib中,其典型实现是向标准错误流发送消息,然后终止程序。返回一个随实现而异的值
可以使用指针参数或引用参数将值返回给调用程序,并使用函数返回指表明成功还是失败。
可以使用全局变量来存储返回条件,通过将全局变量设置为特定的值,调用程序检查变量的值。缺点是必须保证其他函数没有将该全局变量用于其他目的地。
异常机制:由3个部分组成分别是引发异常(throw),使用处理程序捕获异常(catch),使用try块。
throw语句:throw关键字表示引发异常,后面的值指出了异常类型。
例如:
......
throw “bad hmean() arguments: a = -b not allowed ”;
......
被引发的异常是字符串“bad hmean() arguments: a = -b not allowed ”。执行throw语句将终止函数的执行,但是throw不是将控制权返回给调用函数,而是沿函数调用序列后退,直到找到包含try块的函数 异常处理程序(catch块):catch (异常类型){采取的措施}
例如:
......
catch (cosnt char * s)
{
cout << s << endl;
cout << "Enter a new pair of numbers :";
continue;
}
......
关键字catch表明这是一个处理程序,char* s表明该处理函数与字符串异常匹配。并且将匹配的引发付给s,然后执行代码块的代码。
try块:try {可能引发异常的代码}
例如:
......
try{
z=hmean(x,y); //可能引发异常的函数
.....
}
.......
try块后面可以有许多catch块。执行完try块中的语句后,没有引发异常,则程序跳过后面的catch块。如果函数引发异常,但没有匹配的try块或者是处理程序(catch块),程序将调用abort()函数。可以修改这种行为。
通常,引发异常的函数返回是一个对象,有以下优点。
1.可以使用不同的异常类型显示不同函数在不同情况下引发的异常。
2.对象可以携带信息,便于确定引发一场的原因。
异常规范:
1.告诉用户可能需要使用try块。
2.让编译器进行检查是否违反了异常规范。
使用关键字noexcept指出函数不会引发异常。运算符noexcept()用来判断其操作数是否会引发异常。
栈解退:假设函数出现异常,程序会释放栈中的内存,但并不会在释放第一个返回地址后停止,而是继续释放栈,直到找到一个位于try块的返回地址,将程序控制权交给catch块。这个过程是栈解退。c++中,通过将信息放入栈中处理函数调用,程序将调用函数的指令的地址放入栈中,告诉程序调用函数结束后从哪开始执行。
catch (bad_hmean & bg)
{
bg.mesg();
std::cout << "Caught in means()";
throw;
}
上述代码显示信息后,将重新引发这种异常,并将该异常向上发送给main()函数。
程序进行栈解退回到能够捕获异常地方时,将释放栈中的自动变量,如果变量是对象的话,会掉用该对象析构函数。
引发异常时编译器创建一个临时拷贝,即使异常规范和catch块中指定的是引用。
如果有一个异常类继承层次结构,排列的catch块具有顺序:将捕获派生类的catch块放在前面,而捕获基类的catch块放在后面。
如果不知道引发的异常类型,可以使用省略号来表示异常类型,从而捕获任何异常 例如:catch(...){}
在catch语句中使用基类对象时,将捕获所有的派生类对象,但派生类特性将被剥去,将使用虚函数的基类方法。
C++常用的异常
逻辑异常:
invalid_argment异常,接收到一个无效的实参,抛出异常
out_of_range异常,收到一个不在预期范围中的实参,抛出
length_error异常,报告企图产生“长度值超出最大允许值”的对象
domain_error异常,用以报告域错误。
运行时异常:
range_error异常,报告内部计算中的范围错误
overflow_error异常,报告算术溢出错误
underflow_error异常,报告算术下溢错误
以上三个类是由runtime_error类派生的
bad_alloc异常,当new()操作符不能分配所要求的存储区时,抛出异常。由基类exception派生。