总示例代码(GESP真题风格:含除零/参数判断)

以下代码覆盖了GESP 4级异常处理的核心知识点,包含除零错误判断调和平均数(hmean)参数合法性判断等真题常见场景:

#include <iostream>
#include <stdexcept>
using namespace std;

// 场景1:除法运算,判断除零错误(抛出字符串异常)
int divide(int a, int b) {
    if (b == 0) {
        throw "Division by zero error"; // 抛出const char*类型异常
    }
    return a / b;
}

// 场景2:计算调和平均数,判断参数合法性(抛出标准异常)
// 调和平均数公式:hmean = 2ab/(a+b),要求 a != -b
double hmean(double a, double b) {
    if (a == -b) {
        throw runtime_error("hmean: a cannot be equal to -b"); // 抛出标准异常
    }
    return 2.0 * a * b / (a + b);
}

// 场景3:年龄检查,抛出int类型错误码
void checkAge(int age) {
    if (age < 0 || age > 150) {
        throw 400; // 抛出int类型错误码
    }
    cout << "年龄合法:" << age << endl;
}

int main() {
    // 1. 测试除零异常
    try {
        cout << "--- 测试1:除零判断 ---" << endl;
        int res = divide(10, 0); // 触发异常
        cout << "结果:" << res << endl; // 这行不会执行
    } catch (const char* msg) {
        cout << "[捕获字符串异常] " << msg << endl;
    }

    // 2. 测试调和平均数异常
    try {
        cout << "\n--- 测试2:调和平均数参数判断 ---" << endl;
        double val = hmean(10, -10); // 触发异常
        cout << "调和平均数:" << val << endl; // 这行不会执行
    } catch (const runtime_error& e) {
        cout << "[捕获标准异常] " << e.what() << endl;
    }

    // 3. 测试万能兜底捕获
    try {
        cout << "\n--- 测试3:万能兜底捕获 ---" << endl;
        checkAge(200); // 抛出int类型
    } catch (const char* msg) {
        cout << "这行不会执行,类型不匹配" << endl;
    } catch (...) {
        cout << "[万能兜底] 捕获到了未知类型的异常" << endl;
    }

    return 0;
}

一、异常处理机制的核心设计目的

C++的try-catch异常处理机制,唯一核心目的是在程序发生运行时错误时,提供一种结构化的错误处理方式,避免程序直接崩溃,同时将错误处理逻辑与正常业务逻辑分离,提升代码可读性与可维护性。

高频易错排除项

  1. 异常处理不能提高程序运行速度,反而会带来轻微的运行时开销;
  2. 异常处理不负责解决编译错误,编译错误由编译器在编译阶段拦截,与异常机制无关;
  3. 异常处理无法减少程序的内存占用。

二、异常处理的三大核心语法要素

1. try

  • 作用:包裹可能抛出异常的代码,只有在try块内抛出的异常,才会被后续的catch块捕获;
  • 规则:一个try块可以对应多个catch块,try块必须和至少一个catch块配对使用。

2. throw 语句

  • 作用:主动抛出异常,是触发异常处理流程的唯一方式;
  • 规则:通常配合 if 判断使用,在检测到非法输入或运行时错误(如除零、参数越界)时抛出。可以抛出任意类型的异常,包括但不限于:

    • C++标准异常类(如std::runtime_error,需引入<stdexcept>头文件);
    • 字符串常量(如const char*类型);
    • 基础数据类型(如intdouble等)。

3. catch

  • 作用:捕获并处理try块中抛出的异常,可编写多个catch块分别处理不同类型的异常;
  • 特殊语法:catch(...)万能兜底捕获块,可以捕获任意类型的异常,必须放在所有具体类型catch块的最后。

三、异常类型的匹配规则

  1. 精准匹配原则catch块的参数类型必须和throw抛出的异常类型精确匹配,才会进入该catch块执行;

    • 示例:抛出std::runtime_error类型异常,只有catch(const std::runtime_error& e)能精准捕获;抛出const char*类型的字符串异常,只有catch(const char* msg)能精准捕获。
  2. 基类引用可捕获派生类异常:C++标准异常体系中,用基类const std::exception&可以捕获所有派生自它的标准异常(如runtime_error)。
  3. 万能捕获的误区catch(...)可以捕获任意类型的异常,并非只能捕获某一种特定类型。

四、异常抛出后的程序执行流程

  1. 一旦throw抛出异常,立即终止try块中后续所有代码的执行,直接跳转到匹配的catch块;
  2. 匹配到catch块后,会完整执行该catch块内的所有代码;若catch块内有return,会直接终止函数执行,无return则执行完catch后继续执行后续代码。
  3. 异常会沿着函数调用链向上传递:函数内抛出的异常,若当前函数无匹配的catch,会传递给上层调用函数,直到找到匹配的catch,或传递到main函数。

五、未捕获异常的处理机制

  1. 若抛出的异常没有任何匹配的catch,程序不会在编译时报错,而是在运行时调用std::terminate()函数,强制终止程序运行
  2. 核心误区纠正:

    • 不是所有异常都必须被捕获,不捕获的后果是程序终止,而非编译失败;
    • 未匹配的异常只会在运行时触发程序终止,不会在编译阶段报错。

六、高频易错点汇总

说法正确/错误核心原因
如果一个异常在try块中抛出但没有任何catch匹配,它将在编译时报错错误编译不报错,运行时调用std::terminate终止程序
catch(...)只能捕获int类型异常错误catch(...)是万能捕获,可捕获任意类型异常
未捕获异常会调用std::terminate终止程序正确C++标准规定,无匹配catch的异常会触发该函数
如果一个函数可能抛出异常,那么一定要在try子句里调用这个函数错误不放在try中调用,异常会向上传递,并非必须放在try内
所有异常都必须被捕获,否则程序会崩溃错误不是必须捕获,不捕获的标准行为是调用terminate终止程序

标签: none

评论已关闭