[ Pobierz całość w formacie PDF ]

entered (or, if such a handler cannot be found, when the function unexpected() has been
invoked). In order to check whether a thrown exception is currently being processed, you
can use the standard function uncaught_exception() (which is defined in the standard
header ). For example
class FileException{};
File::~File() throw (FileException)
{
if ( close(file_handle) != success) // failed to close current file?
{
if (uncaught_exception() == true ) // is there any uncaught
exception
//being processed currently?
return; // if so, do not throw an exception
throw FileException(); // otherwise, it is safe to throw an
exception
// to signal an error
}
return; // success
}
Still, a better design choice is to handle exceptions within a destructor rather than let
them propagate into the program. For example
void cleanup() throw (int);
class C
{
public:
~C();
};
C::~C()
{
try
{
cleanup();
}
catch(int)
{
//handle the exception within the destructor
}
}
If an exception is thrown by cleanup(), it is handled inside the destructor. Otherwise,
the thrown exception will propagate outside the destructor, and if the destructor has been
invoked while unwinding the stack due to another exception, terminate() will be called.
Global Objects: Construction and Destruction
Conceptually, the construction of global objects takes place before program outset.
Therefore, any exception that is thrown from a constructor of a global object can never be
caught. This is also true for a global object's destructor -- the destruction of a global
object executes after a program's termination. Hence, an exception that is thrown from a
global object's destructor cannot be handled either.
Advanced Exception Handling Techniques
The simple try-throw-catch model can be extended even further to handle more
complicated runtime errors. This section discusses some of the more advanced uses of
exception handling, including exception hierarchies, rethrowing exceptions, function try
blocks and the auto_ptr class.
Standard Exceptions
C++ defines a hierarchy of standard exceptions that are thrown at runtime when abnormal
conditions arise. The standard exception classes are derived from std::exception
(defined in the header). This hierarchy enables the application to catch these
exceptions in a single catch statement:
catch (std::exception& exc)
{
// handle exception of type std::exception as well as
//any exception derived from it
}
The standard exceptions that are thrown by built-in operators of the language are
std::bad_alloc //by operator new
std::bad_cast //by operator dynamic_cast
std::bad_typeid //by operator typeid
std::bad_exception //thrown when an exception specification of
//a function is violatedAll standard exceptions have provided the member function
what(), which returns a const char * with an implementation-dependent verbal
description of the exception. Note, however, that the standard library has an additional set
of exceptions that are thrown by its components.
Exception Handlers Hierarchy
Exceptions are caught in a bottom-down hierarchy: Specific (most derived classes)
exceptions are handled first, followed by groups of exceptions (base classes), and, finally,
a catch all handler. For example
#include
#include
using namespace std;
int main()
{
try
{
char * buff = new char[100000000];
//...use buff
}
catch(bad_alloc& alloc_failure) // bad_alloc is
//derived from exception
{
cout
//... handle exception thrown by operator new
}
catch(exception& std_ex)
{
cout
}
catch(...) // exceptions that are not handled elsewhere are caught
here
{
cout
}
return 0;
}
Handlers of the most derived objects must appear before the handlers of base classes.
This is because handlers are tried in order of appearance. It is therefore possible to write
handlers that are never executed, for example, by placing a handler for a derived class
after a handler for a corresponding base class. For example
catch(std::exception& std_ex) //bad_alloc exception is always handled
here
{
//...handle the exception
}
catch(std::bad_alloc& alloc_failure) //unreachable
{
cout
}
Rethrowing an Exception
An exception is thrown to indicate an abnormal state. The first handle to catch the
exception can try to fix the problem. If it fails to do so, or if it only manages to perform a
partial recovery, it can still rethrow the exception, thereby letting a higher try block
handle it. For that purpose, try blocks can be nested in a hierarchical order, enabling a
rethrown exception from a lower catch statement to be caught again. A rethrow is
indicated by a throw statement without an operand. For example
#include
#include
using namespace std;
enum {SUCCESS, FAILURE};
class File
{
public: File (const char *) {}
public: bool IsValid() const {return false; }
public: int OpenNew() const {return FAILURE; }
};
class Exception {/*..*/}; //general base class for exceptions
class FileException: public Exception
{
public: FileException(const char *p) : s(p) {}
public: const char * Error() const { return s.c_str(); }
private: string s;
};
void func(File& );
int main()
{
try //outer try
{
File f ("db.dat");
func; // 1
}
catch(...) // 7
//this handler will catch the re-thrown exception;
//note: the same exception type is required
{
cout
}
return 0;
}
void func(File & f)
{
try //inner try
{
if (f.IsValid() == false ) [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • burdelmama.opx.pl