Chinaunix首页 | 论坛 | 博客
  • 博客访问: 885400
  • 博文数量: 254
  • 博客积分: 5350
  • 博客等级: 大校
  • 技术积分: 2045
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 13:27
文章分类

全部博文(254)

文章存档

2015年(1)

2014年(9)

2013年(17)

2012年(30)

2011年(150)

2010年(17)

2009年(28)

2008年(2)

分类: C/C++

2011-11-22 14:57:03

  1. /* power.h */
  2. #ifndef __POWER_H
  3. #define __POWER_H

  4. #include <exception>
  5. #include <string>

  6. using namespace std;

  7. class TPowExcept:public exception {
  8.     double b;
  9.     double e;
  10.     string what_str;
  11. public:
  12.     TPowExcept(double b_arg, double e_arg,
  13.         const string &what_arg):
  14.         b(b_arg), e(e_arg), what_str(what_arg) { }
  15.     virtual const char *what() {
  16.         return what_str.c_str();
  17.         }
  18.     ~TPowExcept()throw() { }
  19.     void Report();
  20. };

  21. double power ( double b, double e ) throw (TPowExcept);

  22. #endif

/* power.cpp */
#include
#include
#include "power.h"

using namespace std;

void TPowExcept::Report()
{
    cout << "Domain error: base == " << b
         << ", exponent == " << e << endl;
    cout << what() << endl;
}

double fpower(double b, double e)
{
    return exp(e * log(b));
}

double power(double b, double e) throw(TPowExcept)
{
    if(b > 0.0) return fpower(b,e);
    if (b < 0.0) {
        double ipart;
        double fpart = modf(e, &ipart);
        if (fpart == 0) {
            if (fmod(ipart, 2) != 0)
                return - fpower(-b, e);
            else
                return fpower(-b, e);
            }else
            throw TPowExcept(b, e, "Result is a complex number");
        }else {
            if (e == 0.0) return 1.0;
            if (e < 1.0)
                throw TPowExcept(b, e, "Exponent must be zero or >= 1.0");
            return 0.0;
            }
        //下面这条语句永远不会执行,可以删除
        throw TPowExcept(0, 0, "Error in power () function");
}

/* tpower.cpp */
#include
#include "power.h"

using namespace std;

int main()
{
    double base, exponent, result;
    try {
            cout << "base?";
            cin >> base;
            cout << "exponent?";
            cin >> exponent;
            result = power(base, exponent);
            cout << "result == " << result << endl;
        }
    catch(TPowExcept &except) {
        except.Report();
        return 1;
        }
   
    return 0;
}

g++ -g -c power.cpp
g++ -g tpower.cpp power.o
./a.out



下例演示处理,捕获所有各类未知异常,并改写异常发生时的默认处理动作

  1. /* unexpect.cpp */
  2. #include <iostream>
  3. #include <exception>

  4. using namespace std;

  5. #define MAXERR 10

  6. class MaxError { };

  7. class Error{
  8. private:
  9.     static int count;    //count of error objects
  10. public:
  11.     Error();            //constructor            
  12.     void Say();        //Report static error count
  13. };

  14. void run() throw (Error);
  15. void custom_unexpected();
  16. void custom_terminate();

  17. int Error::count;

  18. int main ()
  19. {
  20.     set_unexpected( custom_unexpected );
  21.     set_terminate( custom_terminate );
  22.     for (;;) {
  23.         try {
  24.             run(); //throws an exception
  25.         }
  26.         catch (Error e) {
  27.             e.Say();
  28.             }
  29.         }
  30.     return 0;
  31. }

  32. void run() throw (Error)
  33. {
  34.     throw Error(); // throw "An unknown exception object"
  35. }

  36. void custom_unexpected()
  37. {
  38.     cout << "Inside custom_unexpected function" << endl;
  39.     throw Error(); //continues program
  40. }

  41. void custom_terminate()
  42. {
  43.     cout << "Inside terminate function" << endl;
  44.     cout << "Exiting program" << endl;
  45.     exit(1);
  46. }

  47. Error::Error()
  48. {
  49.     count++;
  50.     if(count > MAXERR)
  51.         throw MaxError(); //Abort object construction
  52. }

  53. //Error class reporting function
  54. void Error::Say()
  55. {
  56.     cout << "Error: count = " << count << endl;
  57. }


  强制产生10个异常,都是正常处理的。但是,经过10个实例之后程序产生更严重的异常,使自定义处理器收到
这个问题,最后程序优雅地结束并显示一条错误消息--尽管是未定义异常,但并不造成内核转储。
  任何未知异常调用底层函数unexpected()和terminate()函数,可以替换成自定义版本,捕获各种错误
  异常处理中的throw语句产生的效果与函数返回相同,它也引发unwinding stack(函数返回过程中恢复现场的过程)。如果catch不是在throw的直接上层函数中,那么这个unwinding的过程会一直持续,直到找到合适的catch。如果没有合适的 catch,则最后std::unexpected()函数被调用,说明发现了一个没想到的异常,这个函数会调用std::terminate(),这个 terminate()调用abort(),程序终止(core dump)
 这里unexpected()函数调用时也抛出异常,最终引起调用terminate()函数,终止程序。。
  函数抛出异常时,c++自动删除该函数中生成的所有局部变量。如果局部变量是个类对象,则它会导致不可预料后果

/* localexcept.cpp */
#include
#include

using namespace std;

class A {
public:
    A() { cout << "A constructor" << endl; }
    ~A() { cout << "A destructor" << endl; }
};

void f();
int main()
{
    try {
        f();
        }
    catch(const char *s) {
        cout << s << endl;
        }
    return 0;
}

void f()
{
    A a;
    throw("Error condition");
}



这个程序表明正确删除该对象之后,main()中的catch语句才收到抛出异常
但如果函数构造一个由指针动态寻址的对象,则会产生非常不同的效果
假设函数f()构造了对象:
void f()
{
    A *p = new A;
    throw("Error condition");
}
由于所有用new生成的动态对象为全局对象,因此函数因异常而结束时并不调用对象析构器。更糟的是
删除指针p,使对象在太空中浮动,导致内存泄漏

可以用一个标志表示函数中的错误,如果该标志已设置,则先删除任何动态对象,之后抛出异常
bool error_flag;
....
if (error_flag) {
delete p;
throw ("error condition");
}

c++中类的构造器也可能产生异常,无法完成构造函数,这时异常就不用调用析构函数,但在有多个父类时情况变得
复杂;在包含有动态内存的指针时,要小心处理。
阅读(592) | 评论(0) | 转发(0) |
0

上一篇:类的多态

下一篇:C++中的异常(exception)

给主人留下些什么吧!~~