参考:
- 《Essential C++》
- C++ exception类
C++标准库定义了一套异常类体系(exception class hierarchy),其根部是名为exception的抽象基类,标准库抛出的异常都是 exception 的子类,称为标准异常(Standard Exception)。exception声明有一个what()虚函数,会返回一个const char *,用以表示被抛出异常的文字描述。
可以通过下面的语句来捕获所有的标准异常:
try{
// 可能抛出异常的语句
}catch(const exception &e){
// 处理异常的语句
// std::cerr << ex.what() << std::endl;
}
之所以使用引用,是为了提高效率。如果不使用引用,就要经历一次对象拷贝(要调用拷贝构造函数)的过程。
exception 类位于 头文件中,它被声明为:
class exception{
public:
exception () throw(); //构造函数
exception (const exception&) throw(); //拷贝构造函数
exception& operator= (const exception&) throw(); //运算符重载
virtual ~exception() throw(); //虚析构函数
virtual const char* what() const throw(); //虚函数
}
我们可以将自己编写的iterator_overflow继承于exception基类之下。首先必须包含标准头文件exception,而且必须提供自己的what():
iterator_overflow.h :
#ifndef ITERATOR_OVERFLOW_H
#define ITERATOR_OVERFLOW_H
#include <iostream>
#include <exception>
class iterator_overflow : public std::exception
{
public:
iterator_overflow(int index, int max)
: _index(index), _max(max) {}
int index() { return _index; }
int max() { return _max; }
// 不继承exception时作为独立的异常类。
// void what_happened(std::ostream &os = std::cerr)
// {
// os << "Internal error: current index "
// << _index << " exceeds maximum bound: "
// << _max;
// }
// 覆盖 exceptions::what()
// const char *what() const;
// 以上代码会报错:
// looser throw specifier for 'virtual const char* iterator_overflow::what() const'gcc
// 原因如下:
// Since c++11 what() is noexcept.
// You have not declared it as noexcept.
// That is what the 'looser throw specifier' is telling you.
// See http://en.cppreference.com/w/cpp/error/exception/what.
virtual const char *what() const noexcept override;
private:
int _index;
int _max;
};
#endif
将iterator_overflow融入标准的exception类体系的好处是,它可以被任何“打算捕获抽象基类exception”的程序代码所捕获。这意味着我们不必修改原有的程序代码,就可以让那些程序代码认识这个class。
下面是iterator_overflow中what()的具体实现:
operator_overflow.cpp :
#include <sstream>
#include <string>
#include "iterator_overflow.h"
const char *
iterator_overflow::
what() const noexcept
{
std::ostringstream ex_msg;
static std::string msg;
// 将输出信息写到内存的ostringstream对象之中。
// 将整数值转为字符串表示。
ex_msg << "Internal error: current index "
<< _index << " exceeds maximum bound: "
<< _max;
// 萃取出string对象。
msg = ex_msg.str();
// 萃取出const char*表达式。
return msg.c_str();
}
noexcept 用于描述函数不会抛出异常,一旦有异常抛出,会立刻终止程序,它可以阻止异常的传播与扩散。noexcept可以带一个“常量表达式”作为参数,常量表达式为true,表示不会抛出异常,否则代表可以抛出异常。
exception 类的直接派生类:
异常名称 | 说明 |
---|---|
logic_error | 逻辑错误。 |
runtime_error | 运行时错误。 |
bad_alloc | 使用 new 或 new[ ] 分配内存失败时抛出的异常。 |
bad_typeid | 使用 typeid 操作一个 NULL 指针,而且该指针是带有虚函数的类,这时抛出 bad_typeid 异常。 |
bad_cast | 使用 dynamic_cast 转换失败时抛出的异常。 |
ios_base::failure | io 过程中出现的异常。 |
bad_exception | 这是个特殊的异常,如果函数的异常列表里声明了 bad_exception 异常,当函数内部抛出了异常列表中没有的异常时,如果调用的 unexpected() 函数中抛出了异常,不论什么类型,都会被替换为 bad_exception 类型。 |