考纲要求
- 理解异常是程序运行中出现的异常情况,例如除零、越界、文件打开失败。
- 掌握 try 块、throw 语句与 catch 块的作用与执行顺序。
- 能根据异常类型选择对应的 catch 分支,理解按类型匹配的规则。
- 知道未被捕获的异常会终止程序,抛出异常后 try 块内剩余语句不再执行。
典型题型
- 给出 try-catch 程序,要求写出输出结果。
- 判断某个异常会被哪个 catch 分支捕获。
- 在给定场景中选择合理抛出异常的位置。
常见错误
- 以为 throw 之后的语句还会继续执行,实际上控制流直接跳到匹配的 catch。
- catch 的类型与 throw 的类型不匹配,异常没有被捕获,程序终止。
- 在 catch 中再次抛出同类异常却没有外层处理,造成程序异常退出。
- 把异常处理当成调试工具,用异常代替正常的条件判断。
深入理解
try、throw、catch 各管一段
try 包住可能出问题的代码,throw 抛出一个值表示出错了,catch 接住这个值并处理。三者配合的结构是:
try {
if (b == 0) throw 1;
cout << a / b;
} catch (int e) {
cout << "divisor is zero";
}throw 后面跟什么,catch 的括号里就要写什么类型,类型不匹配就接不住。抛出之后函数会立刻退出,沿着调用链往外找第一个能接住它的 catch;一路找不到,程序就崩溃。
抛出之后,try 里剩下的不会执行
这是异常题最常见的考点。一旦 throw 执行,try 块中该语句之后的所有代码都被跳过,直接跳到匹配的 catch。所以「输出什么」类题目要按这个规则逐行推:throw 前面的输出照常,后面的一律不算。
多个 catch 按从上到下顺序匹配,第一个类型相符的被执行,其余跳过。所以具体的类型要写在前面、宽泛的写在后面,否则宽泛的会先接住,具体的永远轮不到。
什么时候该用异常
异常适合处理「罕见且无法就地解决」的错误,例如文件打不开、数组下标越界。普通的业务判断(分数输入是否合法、除数是否为零)更适合用 if 提前拦住——异常的开销比分支判断大,而且会让控制流变得难以追踪。
四级的要求是「了解」:能读懂一段含 try-catch 的程序写出输出、能判断 try 块里哪些语句被跳过即可,不要求在解题时主动设计异常体系。
自编例题
用 try-catch 处理除零
编写函数计算 a 除以 b,当 b 为 0 时抛出异常,并在 main 中捕获输出提示。
double divide(int a, int b) {
if (b == 0) throw runtime_error("divided by zero");
return (double)a / b;
}
int main() {
try { cout << divide(6, 0) << endl; }
catch (const runtime_error &e) { cout << e.what() << endl; }
return 0;
}divide 在发现除数为 0 时抛出 runtime_error,控制流立刻离开 divide,try 块中剩余的语句不再执行,跳到类型匹配的 catch 分支,输出异常信息。catch 用 const 引用接收,避免复制异常对象。若没有任何 catch 匹配,异常会继续向外传播,最终导致程序终止。异常适合处理「正常流程之外、调用方需要知道」的错误,普通的可预期分支用 if 判断更清晰。
相关真题
这块内容在整条路线里的位置:GESP C++ 4 级备考路径。
READY TO START
开始练习
先做一套本级别测评,报告会指出哪些知识点需要重点补;再回到本页对照考纲要求逐条核对,把不确定的条目记下来集中练。
常见问题
什么时候应该用异常?
当错误无法在当前位置处理、需要通知调用方,或错误来自深层调用时使用异常;普通条件分支直接用 if 更简单。
异常和返回值报错哪个好?
返回值报错直观但容易被忽略,异常不会被无意忽略但开销较大。按团队约定和错误性质选择,不要混用同一套接口。
catch 的顺序有影响吗?
有。catch 按出现顺序匹配,子类异常应写在父类之前,否则会被父类分支先捕获,子类分支永远执行不到。
