#include <stdexcept>
C++标准本身提供的异常类完全能够满足任何规模程序的使用。
为何要用异常
下面首先引用《C++ 程序设计语言》中的段落来描述C++异常的目标(虽然该书描述为何需要异常时已经非常全面,这里只简单列举最为重要的思想):
1 当程序是由相互分离的模块组成时,库的作者可以检查出运行时错误,但是一般却不知道怎样去处理他们(抛出异常);用户的代码知道如何处理他们(捕获异常),却又无法检查它们(因为异常发生在库的代码中)
2 将错误的产生和错误的处理分离(解耦);库不应该单方面终止程序,而应该抛出异常,让调用者去做决定。
3 (不重要)代码更易读。
以上两点可以说是最为重要的理由了。如果没有异常,我们的程序就会用返回值来层层传递,代码量陡然增加。
其机制如下:
1 基类exception:
a)C++提供了标准异常类exception,这个类是所有标准异常的基类,其析构函数为虚函数
b)提供统一接口 const char* what() const 来作为各种标准异常对外的唯一接口
c)捕获任何标准异常只需要捕获这个类的引用即可捕捉到各种标准异常
d)之所以需要异常是因为可以在某个局部代码中只捕获某一种派生异常,其他异常留到外面去处理,认为当前地方处理不了。而异常抛出的时候并不复杂,只需要告诉外面,这里为啥出问题了,一个字符串就说清楚了。更多的信息看起来有用,得不偿失。
2 各种标准异常
a)标准异常的构造函数必须提供显示异常类型以及字符串参数作为构造函数的参数,也就是说异常发生之后我们只需要catch到这个异常并调用what方法看看发生了什么事情就足够了
c)如果你用字符串作为抛出异常的类型,你只能捕获字符串类型的异常,而不可能是string,也不可能是任何标准异常
d)抛出什么类型就只能捕获什么类型,或者这个类型的基类型。
e)!!!!!自定义异常类型基本上可以认为是多此一举!!!!!!!!(在众多工程中管理这个异常类的头文件和源文件不胜其烦),因为我们只需要获取what就可以解决问题
3 标准用法示例代码
void testException(void)
{
try
{
int a = 0;
throw runtime_error("runtime_error");
}
catch (exception& e)
{
cout << "catched:" << e.what() << endl;
}
try
{
int a = 0;
throw logic_error("logic_error");
}
catch (exception& e)
{
cout << "catched:" << e.what() << endl;
}
try
{
int a = 0;
throw "str_error";
}
catch (const exception& e)
{
cout << "catched exception : " << e.what() << endl;
}
catch (const string& e)
{
cout << "catched string : " << e.c_str() << endl;
}
catch (const char* e)
{
cout << "catched const char * :" << e << endl;
}
}
看输出就知道了
补充:
1) C语言那种错误码处理维护成本高,适合实时性要求高,出了问题要处理的情况,不能抛异常。