曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4183|回复: 0
打印 上一主题 下一主题

异常类

[复制链接]

716

主题

734

帖子

2946

积分

超级版主

Rank: 9Rank: 9Rank: 9

积分
2946
跳转到指定楼层
楼主
发表于 2014-1-2 22:45:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
exception 头文件(以前为 exception.h 或 except.h)定义了 exception 类,C++ 可以把它作为其他异常类的基类。其中,有一个名为 what() 的虚拟成员函数,它返回一个字符串,该字符串的特征随实现而异,比如通过 VC++ 编译器可以看到该函数的定义:
  1. virtual const char * __CLR_OR_THIS_CALL what() const _THROW0()                {        // return pointer to message string
  2.                 return (_Ptr != 0 ? _Ptr : "unknown exception");
  3.                 }
复制代码
这是个虚方法,在 exception 的派生类中可以重新定义它,比如:
  1. #include <exception>
  2. class bad_hmean : public std::exception
  3. {
  4.     public:
  5.        const char * what() { return "bad arguments to hmean()"; }
  6.        ...
  7. };

  8. class bad_gmean : public std::exception
  9. {
  10.     public:
  11.         const char * what() { return "bad arguments to gmean()"; }
  12.         ...
  13. };
复制代码
上面定义了两个派生的异常类,这样可以针对每一种进行相应的处理。如果不想这么做,可以在同一个基类处理程序中捕获它们:
  1. try {
  2. ...
  3. }
  4. catch (std::exception & e)
  5. {
  6.     cout << e.what() << endl;
  7.     ...
  8. }
复制代码
事实上,C++ 库定义了许多基于 exception 的异常类型。

1. stdexcept 异常类

头文件 stdexcept 定义了其它几个异常类,比如 logic_error 和 runtime_error 类,它们都以公有方式从 exception 派生而来:
  1. class logic_error : public exception {
  2. public:
  3. explicit logic_error(const string& what_arg);
  4. ...
  5. };
  6. class domain_error : public logic_error {
  7. public:
  8. explicit domain_error(const string& what_arg);
  9. ...
  10. };
复制代码
这些类的构造函数接受一个 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 中新增的异常规范功能,它的形式如:
  1. double marm(double) throw(bad_thing);
复制代码
其中 throw() 部分就是异常规范,它的作用之一是:告诉用户可能需要使用 try 块。那么当用户使用了 try 块后,若是产生了异常,catch 就能将异常捕捉下来。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-30 10:09 , Processed in 0.066852 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表