1. 异常
- 程序出现问题时,通过抛出(throw)⼀个对象来引发⼀个异常,抛出对象的类型决定了由哪个catch语句来解决异常
c
#include<iostream>
using namespace std;
double Divide(int a, int b)
{
try
{
// 当b == 0时抛出异常
if (b == 0)
{
string s("Divide by zero condition!");
throw s;
}
else
{
return ((double)a / (double)b);
}
}
catch (int errid)
{
cout << errid << endl;
}
return 0;
}
void Func()
{
int len, time;
cin >> len >> time;
try
{
cout << Divide(len, time) << endl;
}
catch (const char* errmsg)
{
cout << errmsg << endl;
}
cout << __FUNCTION__ << ":" << __LINE__ << "行执行" << endl;
}
int main()
{
while (1)
{
try
{
Func();
}
catch (const string& errmsg)
{
cout << errmsg << endl;
}
}
return 0;
}
这里就是由main函数里的catch来捕获异常
-
捕捉异常类型一样时,离抛异常调用链近的优先调用,这里把Func()里的捕捉异常类型改成 string &errmsg时,就会调用Func里的catch
-
无论是否抛异常,throw后面的语句都不会被执行,如果不抛异常会继续执行try后面的语句
-
⼀旦程序开始执行异常处理程序,沿着调用链创建的对象都将销毁,这里在跳到main函数栈帧里执行catch之前,会先把Func里的对象都销毁
-
抛出异常对象后,会生成⼀个异常对象的拷贝,因为抛出的异常对象可能是⼀个局部对象,所以会生成一个拷贝对象,这个拷贝的对象会在catch语句后销毁(这里的处理类似于函数的传值返回)
2. 栈展开

-
如果当前函数中没有try/catch语句,或者有try/catch语句但是类型不匹配,则退出当前函数,继续
在外层调用函数链中查找,这个查找catch过程被称为栈展开 -
如果到达main函数,依旧没有找到匹配的catch子句,程序会调用标准库的 terminate 函数终止程序。
-
如果找到匹配的catch子句处理后,catch子句代码都会继续执行。

-
允许权限缩小,可以拿const char捕获char,也可以拿基类对象的指针或引用捕获派生类对象
-
如果到main函数,异常仍旧没有被匹配就会终止程序,所以⼀般main函数中最后都会使用catch(...),它可以捕获任意类型的异常,但是是不知道异常错误是什么
-
noexcept是不会抛出异常,在函数后面写了,即使发生了异常也不会捕获
