exception 头文件(以前为 exception.h 或 except.h)定义了 exception 类,C++ 可以把它作为其他异常类的基类。其中,有一个名为 what() 的虚拟成员函数,它返回一个字符串,该字符串的特征随实现而异,比如通过 VC++ 编译器可以看到该函数的定义:- virtual const char * __CLR_OR_THIS_CALL what() const _THROW0() { // return pointer to message string
- return (_Ptr != 0 ? _Ptr : "unknown exception");
- }
复制代码 这是个虚方法,在 exception 的派生类中可以重新定义它,比如:- #include <exception>
- class bad_hmean : public std::exception
- {
- public:
- const char * what() { return "bad arguments to hmean()"; }
- ...
- };
- class bad_gmean : public std::exception
- {
- public:
- const char * what() { return "bad arguments to gmean()"; }
- ...
- };
复制代码 上面定义了两个派生的异常类,这样可以针对每一种进行相应的处理。如果不想这么做,可以在同一个基类处理程序中捕获它们:- try {
- ...
- }
- catch (std::exception & e)
- {
- cout << e.what() << endl;
- ...
- }
复制代码 事实上,C++ 库定义了许多基于 exception 的异常类型。
1. stdexcept 异常类
头文件 stdexcept 定义了其它几个异常类,比如 logic_error 和 runtime_error 类,它们都以公有方式从 exception 派生而来:- class logic_error : public exception {
- public:
- explicit logic_error(const string& what_arg);
- ...
- };
- class domain_error : public logic_error {
- public:
- explicit domain_error(const string& what_arg);
- ...
- };
复制代码 这些类的构造函数接受一个 string 对象作为参数,该参数为 what() 以 C 风格字符串返回字符数据。
总的来说,每个类的名称指出了它用于报告的错误类型。比如:
domain_error 用来指出数学函数上值域发生错误所引发的异常。
invalid_argument 用来指出给函数传递了一个非法参数。
length_error 用来指出没有足够的空间来执行所需的操作。
out_of_bounds 通常用于指示索引错误。
runtime_error 系列异常描述了可能在运行时发生的难以预料及防范的错误。
bad_alloc 异常和 new
头文件 new 包含了 bad_alloc 类的声明,它从 exception 类公有派生而来。在以前,当无法分配请求的内存量时,new 返回一个空指针。考虑下面的程序:
[C++] 纯文本查看 复制代码 // newexcp.cpp -- the bad_alloc exception
#include <iostream>
#include <new>
#include <cstdlib> // for exit(), EXIT_FAILURE
using namespace std;
struct Big
{
double stuff[20000];
};
int main()
{
Big * pb;
try {
cout << "Trying to get a big block of memory:\n";
pb = new Big[10000]; // 1,600,000,000 bytes
cout << "Got past the new request:\n";
}
catch (bad_alloc & ba)
{
cout << "Caught the exception!\n";
cout << ba.what() << endl;
exit(EXIT_FAILURE);
}
cout << "Memory successfully allocated\n";
pb[0].stuff[0] = 4;
cout << pb[0].stuff[0] << endl;
delete [] pb;
// cin.get();
return 0;
}
在上面的程序中,当由于分配大量的内存而导致失败时,会抛出 bad_alloc 类异常,这会被 catch 捕捉。
有可能会问,这里没有 throw ,怎么还会被 catch 捕捉到异常?原因是在 new 头文件中,使用了 C++98 中新增的异常规范功能,它的形式如:- double marm(double) throw(bad_thing);
复制代码 其中 throw() 部分就是异常规范,它的作用之一是:告诉用户可能需要使用 try 块。那么当用户使用了 try 块后,若是产生了异常,catch 就能将异常捕捉下来。
|