一、什么是异常
异常一般是指程序运行期发生的非正常情况。异常一般是不可预测的,如:内存不足,打开文件失败,数组越界,范围溢出等。
在某段程序发生无法继续正常执行的情况时,C++允许程序进行所谓抛出异常(有时候也称为吐出异常)的行为。
二、异常的特性
异常从触发点开始向外传播,直到被捕获(有时候也被称为吞下异常),如果没有被捕获程序就终止。
三、怎么处理异常
异常处理的核心思想是,把功能模块代码与系统中可能出现的错误代码分离开来,以此来达到代码组织更美观,逻辑上更清晰,并且同时从根本上来提高我们软件系统长时间稳定运行的可靠性。
// 语法简单示例: try { // 执行可能抛出异常的代码 int fd = open("1.txt", O_RDONLY); if(fd == -1) { throw -1; } } catch(int i) // 捕获整形异常 { cout << i << endl; } catch(...) // 捕获其他异常 { cout << "other execption" << endl; }
四、异常安全问题
1、由于抛出的异常只要找到匹配的catch就直接跳到catch块执行,没有找到对应catch的函数就不会继续执行,这样会导致函数的执行流程很乱,可能会导致一些问题。
2、构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能会导致对象不完整或者没有完全初始化。
3、析构函数主要完成资源的清理,最好不要在析构函数中抛出异常,否则可能导致内存泄漏。
五、案例
1、异常最简单使用
#include <iostream> using namespace std; int main() { // 计算两个整形数之间的除法 cout << "please input a, b " << endl; int a, b; while(1) { cin >> a >> b; try { if(b == 0) { throw -1; // 抛出整型异常 } else { cout << a << " / " << b << " = " << (float)a/b << endl; break; } } catch(int e) // 捕获整型异常 { cout << "b == 0 is illegal, please input a, b again" << endl; continue; } } cout << "sucess" << endl; return 0; }
2、异常类使用
声明一个异常类作为基类,然后其派生类为异常的具体类型,采用多态的思想来解决捕获单个不同类型的异常。
#include <iostream> using namespace std; // 异常基类 class Exception { protected: string _errmsg; // 错误信息 int _id; // 错误码 public: Exception(const string &msg = string(), int id = 0) { _errmsg = msg; _id = id; } virtual void handle() = 0; }; // 数据处理异常类 class DataException: public Exception { public: DataException(const string &msg = string(), int id = 1):Exception(msg, id) { } void handle() { cout << "DataException" << endl; cout << "errmsg:" << _errmsg << " id: " << _id << endl; } }; // 网络异常类 class HttpException: public Exception { public: HttpException(const string &msg = string(), int id = 2):Exception(msg, id) { } void handle() { cout << "HttpException" << endl; cout << "errmsg:" << _errmsg << " id: " << _id << endl; } }; int main() { try { throw DataException("data is illegal", 1); } catch(Exception &e) { e.handle(); } cout << endl; try { throw HttpException("network disconnect", 2); } catch(Exception &e) { e.handle(); } return 0; }
六、总结
异常可以使用自己声明的,也可以使用C++提供的。异常把功能模块代码和错误处理代码分开,使逻辑更加清晰,但是使用异常也会带来一些问题,需要注意。