异常
异常是面向对象语言处理错误的一种方式。当一个函数出现自己无法处理的错误时,可以抛出异常,然后输的直接或者间接调用者处理这个错误。
语法
捕获全部的异常
try
{
//可能抛出异常的代码
//throw异常对象
}
catch(...)
{
//不管什么异常,都在这里统一处理
}
捕获指定的异常
try
{
// 可能抛出异常的代码。
// throw 异常对象;
}
catch (exception1 e)
{
// 发生exception1异常时的处理代码。
}
catch (exception2 e)
{
// 发生exception2异常时的处理代码。
}
在try语句块中,如果没有发生异常,执行完try语句块中的代码后,将继续执行try语句块之后的代码;如果发生了异常,用throw抛出异常对象,异常对象的类型决定了应该匹配到哪个catch语句块,如果没有匹配到catch语句块,程序将调用abort()函数中止。
如果try语句块中用throw抛出异常对象,并且匹配到了catch语句块,执行完catch语句块中的代码后,将继续执行catch语句块之后的代码,不会回到try语句块中。
如果程序中的异常没有被捕获,程序将异常中止。
catch是通过throw抛出的对象匹配的;
catch(...)可以捕获任意类似的对象,主要捕获自己都不知道的异常;
下面看几个例子
try语句块中代码出现异常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test()
{
array<int, 5> a = { 1,2,3,4,5 };
//try
//{
// int a1 = a[5];
// cout << a1 << endl;
//}
//catch(exception e)
//{
// cout << "1越界了" << endl;
//}
try
{
int a2 = a.at(5);
cout << a2 << endl;
}
catch (exception e)
{
cout << "2越界了" << endl;
}
}
int main()
{
test();
return 0;
}
这里由于第一个数组越界程序直接崩溃,注释掉,运行,结果如下
因为at会检查是否越界,当访问越界时会抛出异常,从而catch发挥作用。
try语句中抛出异常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test1()
{
try
{
throw"未知错误";
cout << "语句1" << endl;
}
catch (const char* e)
{
cout << e << endl;
}
}
int main()
{
test1();
return 0;
}
我们发现try语句块中throw后面的语句没有执行,我们继续观察
try语句中的函数抛出异常
#include<iostream>
#include<exception>
#include<array>
using namespace std;
void func()
{
throw"未知错误!";
cout << "func()中" << endl;
}
void test2()
{
try
{
func();
cout << "try中" << endl;
}
catch (const char* e)
{
cout << e << endl;
}
}
int main()
{
test2();
return 0;
}
这里我们发现try语句中抛出异常函数后面的语句和函数体抛出语句后面的语句没有执行。
这是为什么呢??
在函数调用链中异常展开匹配原则
1. 首先检查 throw 本身是否在 try 块内部,如果是再查找匹配的 catch 语句,如果有匹配的,则调到catch的地方进行处理;
2. 没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch;
3. 如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的catch子句的 过程称为 栈展开,也称栈解旋。所以实际中我们最后都要加一个catch(…)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
4. 找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
#include<iostream>
#include<exception>
using namespace std;
void func1()
{
throw"多级函数调用的未知错误";
}
void func2()
{
func1();
}
void func3()
{
func2();
}
void test3()
{
try
{
func3();
cout << "try中" << endl;
}
catch (...)
{
cout << "未知错误" << endl;
}
}
int main()
{
test3();
return 0;
}
总结:没有找到匹配的函数栈就会被释放。
把上述代码进行修改如下
#include<iostream>
#include<exception>
using namespace std;
void func1()
{
throw"多级函数调用的未知错误";
}
void func2()
{
try
{
func1();
}
catch(const char* e)
{
cout << e << endl;
}
}
void func3()
{
func2();
}
void test3()
{
try
{
func3();
cout << "try中" << endl;
}
catch (...)
{
cout << "未知错误" << endl;
}
}
int main()
{
test3();
return 0;
}
多级catch
下面给出例子
#include<iostream>
using namespace std;
int main()
{
cout << "1-错误A,2-错误B,other-未知错误" << endl;
cout << "请输入:";
int x = 0;
while (cin >> x)
{
try
{
if (x == 1)
throw"错误A";
else if (x == 2)
throw"错误B";
else
throw"未知错误";
}
catch(const char* e)
{
cout << e << endl;
}
cout << "请输入:";
}
return 0;
}