解锁C++异常秘籍:自定义类与安全保障全解析

目录

一、C++ 异常处理初印象

二、探索 C++ 标准异常类

三、自定义异常类的构建与应用

3.1 自定义异常类的必要性

3.2 自定义异常类的实现步骤

3.3 实际应用场景

四、异常安全保证:守护代码的坚固防线

4.1 异常安全的重要性

4.2 异常安全的三个级别

4.3 实现异常安全的策略与技巧

五、总结与展望


一、C++ 异常处理初印象

        在 C++ 编程的世界里,我们常常会遇到各种意外情况,比如除零错误、内存分配失败、数组越界等。这些运行时错误如果不妥善处理,可能会导致程序崩溃,给用户带来糟糕的体验。为了应对这些问题,C++ 引入了异常处理机制。

        C++ 的异常处理主要通过try、catch和throw这三个关键字来实现。try块用于包含可能会抛出异常的代码,就像是一个 “安全区”,在这个区域内执行的代码如果遇到问题,就会抛出异常。catch块则用于捕获并处理这些异常,它就像是一个 “异常捕捉器”,专门等待捕获从try块中抛出的异常,并执行相应的处理逻辑。而throw关键字则用于抛出异常,当程序遇到错误情况时,通过throw来通知调用者发生了异常,并传递异常信息。

        例如,下面这段简单的代码演示了基本的异常处理:

#include <iostream>

int main() {

int numerator = 10;

int denominator = 0;

try {

if (denominator == 0) {

throw "除数不能为零";

}

int result = numerator / denominator;

std::cout << "结果是: " << result << std::endl;

} catch (const char* msg) {

std::cerr << "捕获到异常: " << msg << std::endl;

}

return 0;

}

        在这个例子中,我们在try块中进行除法运算,如果发现除数为零,就使用throw抛出一个字符串类型的异常。catch块捕获到这个异常,并输出相应的错误信息。这样,即使程序遇到了除零错误,也不会直接崩溃,而是能够优雅地处理这个异常情况。

        不过,在实际应用中,仅仅使用基本的异常处理机制是不够的。对于复杂的程序,我们往往需要自定义异常类,以便更精确地处理各种不同类型的异常,同时确保程序的异常安全性。这就是我们接下来要深入探讨的内容。

二、探索 C++ 标准异常类

        在深入了解自定义异常类之前,先来熟悉一下 C++ 标准库中已经提供的异常类。C++ 标准库定义了一系列的异常类,它们形成了一个层次结构,std::exception是所有标准异常类的基类。

        std::exception类提供了一个虚函数what(),用于返回一个描述异常的字符串。这个基类为所有标准异常提供了一个统一的接口,方便我们在捕获异常时获取异常信息。

        从std::exception派生出来的子类有很多,其中一些常见的包括:

  • std::runtime_error:用于表示运行时错误,这类错误在程序运行时才能检测到,例如除零错误、无效的参数值等。它有多个重要的子类,如std::overflow_error(表示算术运算上溢)和std::underflow_error(表示算术运算下溢) 。在进行数值计算时,如果计算结果超出了数据类型所能表示的范围,就可以抛出std::overflow_error或std::underflow_error异常。比如:

#include <iostream>

#include <stdexcept>

int main() {

try {

int a = 2147483647; // 这是int类型的最大值

int b = 1;

int result = a + b; // 这里会发生上溢

std::cout << "结果是: " << result << std::endl;

} catch (const std::overflow_error& e) {

std::cerr << "捕获到上溢异常: " << e.what() << std::endl;

}

return 0;

}
  • std::logic_error:用于表示逻辑错误,这类错误是在程序逻辑设计上的问题,理论上在编译时就可以避免。例如std::invalid_argument(表示无效参数),当函数接收到一个不符合预期的参数时,可以抛出这个异常。比如一个函数要求传入的参数必须是正数,如果传入了负数,就可以抛出std::invalid_argument异常:

#include <iostream>

#include <stdexcept>

void calculate(int num) {

if (num <= 0) {

throw std::invalid_argument("参数必须是正数");

}

// 正常计算逻辑

std::cout << "计算结果是: " << num * 2 << std::endl;

}

int main() {

try {

calculate(-1);

} catch (const std::invalid_argument& e) {

std::cerr << "捕获到无效参数异常: " << e.what() << std::endl;

}

return 0;

}
  • std::bad_alloc:当new操作符无法分配足够的内存时,会抛出这个异常。在进行动态内存分配时,比如创建一个大型数组或对象时,如果内存不足,就会触发std::bad_alloc异常:

#include <iostream>

#include <stdexcept>

int main() {

try {

int* largeArray = new int[1000000000]; // 尝试分配大量内存,可能会失败

} catch (const std::bad_alloc& e) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大雨淅淅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值