1.C语言的错误处理方式
1.1直接终止程序
利用assert和exit都是直接终止程序。
1.2返回错误码
例如C语言程序的很对接口函数都会将错误信息存储在errno中表示错误。当我们自己设计函数时,函数返回值和返回错误码容易混淆,且如果函数调用栈较深时,一层层返回很难处理。
2.C++异常处理
2.1异常定义
异常是面向对象语言处理错误的一种方式,它主要由三个关键部分组成:throw 抛出异常
try 中放置可能会抛异常的代码,catch 用于捕获异常。
如下代码,是我们捕获的C++中的异常。
vector<int> v{ 1,2,5,6,4,5 };
try
{cout << v.at(10)<< endl;
}
catch (const exception& e)
{cout << e.what() << endl; //invalid vector subscript
}
return 0;
我们还可以自己设计自己的函数,并抛出异常。
int divi(const int& x1, const int& x2) {if (x2 == 0) {throw string("除数为零");}return x1 / x2;
}int main() {try {cout << divi(10, 0) << endl;}catch (const string& e) {cout << e << endl;}
理论上讲,throw抛出的异常我们可以任意设计但是在公司设计时,我们抛出的常常是派生类,然后用基类来捕获。 这样设计可以更加的规矩,有序。
class Exception {
public:Exception(const int& id, const string& errmsg):_id(id),_errmsg(errmsg){}virtual string what()const = 0; //纯虚类
protected:int _id;string _errmsg;
};class SqlException :public Exception {
public:SqlException(const int& id,const string& errmsg):Exception(id,errmsg){}virtual string what() const{return "SQL :" + _errmsg;}
};class CacheException :public Exception {
public:CacheException(const int& id, const string& errmsg):Exception(id, errmsg){}virtual string what() const{return "Cache:" + _errmsg;}
};
void func1()
{if (rand() % 9 == 0) {throw SqlException(100, "权限不足");}
}int main() {srand(time(NULL));int n = 10;while (n){try {func1();}catch (const Exception& e) { //利用了多态cout << e.what() << endl;}catch(...){cout << "处理成功" <<endl;}n--;}
}
2.2异常的安全问题
void func2() {char* arr = new char;if (rand() % 9 == 0)throw string("抛出异常");delete arr;
}
例如当我们调用func2函数时,有可能会抛出异常,那么arr就不能被delete掉,造成内存泄漏。我们可以利用异常重抛出,来解决内存泄漏问题。
void func2() {char* arr = new char;try{if (rand() % 9 == 0)throw string("抛出异常");}catch (...) { //如果有异常,则捕获全部异常,这里捕获后用来delete掉arr//然后重新抛出异常delete arr;throw;}delete arr;
}
我们还可以利用RAII来解决此类问题。
我们在构造函数和析构函数时最好不要抛出异常,不然容易导致资源泄漏和对象初始化不完全。
2.3 c++中的异常库
c++中的异常库都从exception基类派生出来的,因此我们捕获c++库函数的异常时,只需要捕获基类的exception,利用多态的原理,访问what函数即可得到错误信息。
2.4异常抛出和使用的原则
2.5异常在函数栈上的捕获
2.6异常的优缺点
优点①抛出的类定义好后可以清晰的获得错误的信息
②多层调用时,里面的抛出异常后,不需要层层传递,直接在需要的地方catch即可。
③能很好解决c语言中没返回值不能返回错误码的问题,以及返回的错误码和返回值混淆的问题。
④很多第三方库都包含异常。
缺点①导致程序执行顺序混乱
②C++没有垃圾回收机制,容易出现死锁和内存泄漏问题,需要RAII解决
③使用不规范问题。