- /* power.h */
-
#ifndef __POWER_H
-
#define __POWER_H
-
-
#include <exception>
-
#include <string>
-
-
using namespace std;
-
-
class TPowExcept:public exception {
-
double b;
-
double e;
-
string what_str;
-
public:
-
TPowExcept(double b_arg, double e_arg,
-
const string &what_arg):
-
b(b_arg), e(e_arg), what_str(what_arg) { }
-
virtual const char *what() {
-
return what_str.c_str();
-
}
-
~TPowExcept()throw() { }
-
void Report();
-
};
-
-
double power ( double b, double e ) throw (TPowExcept);
-
- #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
下例演示处理,捕获所有各类未知异常,并改写异常发生时的默认处理动作
- /* unexpect.cpp */
-
#include <iostream>
-
#include <exception>
-
-
using namespace std;
-
-
#define MAXERR 10
-
-
class MaxError { };
-
-
class Error{
-
private:
-
static int count; //count of error objects
-
public:
-
Error(); //constructor
-
void Say(); //Report static error count
-
};
-
-
void run() throw (Error);
-
void custom_unexpected();
-
void custom_terminate();
-
-
int Error::count;
-
-
int main ()
-
{
-
set_unexpected( custom_unexpected );
-
set_terminate( custom_terminate );
-
for (;;) {
-
try {
-
run(); //throws an exception
-
}
-
catch (Error e) {
-
e.Say();
-
}
-
}
-
return 0;
-
}
-
-
void run() throw (Error)
-
{
-
throw Error(); // throw "An unknown exception object"
-
}
-
-
void custom_unexpected()
-
{
-
cout << "Inside custom_unexpected function" << endl;
-
throw Error(); //continues program
-
}
-
-
void custom_terminate()
-
{
-
cout << "Inside terminate function" << endl;
-
cout << "Exiting program" << endl;
-
exit(1);
-
}
-
-
Error::Error()
-
{
-
count++;
-
if(count > MAXERR)
-
throw MaxError(); //Abort object construction
-
}
-
-
//Error class reporting function
-
void Error::Say()
-
{
-
cout << "Error: count = " << count << endl;
- }
强制产生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++中类的构造器也可能产生异常,无法完成构造函数,这时异常就不用调用析构函数,但在有多个父类时情况变得
复杂;在包含有动态内存的指针时,要小心处理。