Menu
CoddyTech

面向对象编程中的异常处理

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 81 课,共 104 课。

C++ 中的异常处理提供了一种结构化的方式来检测和响应运行时错误。在面向对象编程中,异常可以自然地融入类层次结构,让你创建有意义的错误类型,并携带有关错误原因的上下文信息。

基本机制使用三个关键字:try、throw 和 catch。可能失败的代码放在 try 块中,使用 throw 发出错误信号,而 catch 块用于处理特定类型的异常:

#include <iostream>
#include <stdexcept>

class BankAccount {
    double balance;
public:
    BankAccount(double b) : balance(b) {}
    
    void withdraw(double amount) {
        if (amount > balance) {
            throw std::runtime_error("Insufficient funds");
        }
        balance -= amount;
    }
    
    double getBalance() const { return balance; }
};

int main() {
    BankAccount account(100.0);
    
    try {
        account.withdraw(150.0);
    } catch (const std::runtime_error& e) {
        std::cout << "Error: " << e.what() << "\n";
    }
    
    std::cout << "Balance: " << account.getBalance() << "\n";
}

C++ 标准库提供了一组以 std::exception 为根类的异常类层次结构。常见的派生类包括用于运行时问题的 std::runtime_error 和用于编程错误的 std::logic_error。所有标准异常都提供一个 what() 方法,用于返回错误消息。

抛出异常时,栈会展开,程序会在查找匹配的 catch 块时调用所有局部对象的析构函数。这样即使发生错误,也能确保正确清理,这就是 RAII 和异常处理配合得如此好的原因。

challenge icon

挑战

简单

让我们构建一个安全的除法计算器,在面向对象的场景中演示异常处理。你将创建一个 Calculator 类来执行除法运算,并在出错时抛出有意义的异常,然后在主程序中妥善处理这些异常。

你将把代码分成三个文件:

  • Calculator.h:定义 Calculator 类,用于执行数学运算并妥善处理错误。

    你的 Calculator 应该有一个方法 divide(double numerator, double denominator),用于返回除法结果。不过,如果分母为零,就应该抛出一个 std::runtime_error,并附带消息 Division by zero。如果分子或分母为负数,就应该抛出一个 std::invalid_argument,并附带消息 Negative values not allowed。

    还要添加一个方法 safeSqrt(double value),用于返回该值的平方根。如果该值为负数,就抛出一个 std::runtime_error,并附带消息 Cannot compute square root of negative number。你需要引入 <cmath>,以使用 sqrt 函数。

  • Calculator.cpp:实现头文件中声明的方法。确保引入必要的头文件(<stdexcept> 和 <cmath>),并在执行运算前检查条件。
  • main.cpp:读取三个输入(每个输入单独占一行):
    1. 运算类型:divide 或 sqrt
    2. 第一个数字(double)
    3. 第二个数字(double):仅用于除法,执行 sqrt 时会忽略

    创建一个 Calculator 对象,并在 try 块中执行请求的运算。如果运算成功,打印 Result: [value]。如果捕获到异常,则打印 Error: [message],其中消息来自异常的 what() 方法。

    在 try-catch 块之后(无论是否发生异常),打印 Calculation complete,以演示程序在处理异常后会继续执行。

例如,输入 divide、10 和 2 时:

Result: 5
Calculation complete

输入 divide、10 和 0 时:

Error: Division by zero
Calculation complete

输入 divide、-5 和 2 时:

Error: Negative values not allowed
Calculation complete

输入 sqrt、16 和 0 时:

Result: 4
Calculation complete

输入 sqrt、-9 和 0 时:

Error: Cannot compute square root of negative number
Calculation complete

注意,程序会通过捕获异常并显示有意义的消息来妥善处理错误,然后继续执行。这种模式能让错误处理保持简洁,并让主逻辑专注于正常流程。

亲手试试

#include <iostream>
#include <string>
#include "Calculator.h"

using namespace std;

int main() {
    // 读取输入
    string operation;
    double num1, num2;
    
    cin >> operation;
    cin >> num1;
    cin >> num2;
    
    // 创建 Calculator 对象
    Calculator calc;
    
    // TODO: 使用 try-catch 块执行运算
    // 如果 operation 是 "divide",调用 calc.divide(num1, num2)
    // 如果 operation 是 "sqrt",调用 calc.safeSqrt(num1)
    // 成功时,打印 "Result: ",然后打印结果
    // 捕获异常,打印 "Error: ",然后打印异常消息(使用 what())
    // 在 try-catch 之后,始终打印 "Calculation complete"
    
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器