面向对象编程中的异常处理
本课属于 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 和异常处理配合得如此好的原因。
挑战
简单让我们构建一个安全的除法计算器,在面向对象的场景中演示异常处理。你将创建一个 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:读取三个输入(每个输入单独占一行):- 运算类型:
divide或sqrt - 第一个数字(double)
- 第二个数字(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;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器