Exception

Exception is an object, so must throw an object of any type (class, string, built-in data type, enum).
throw ClassName(); // class constructor

A try block introduces a local scope and variables declared within a try block cannot be referred to outside the try block, including within the catch clauses.

Exception declaration of the catch clause can be single type or single object. An object should be declared when it is necessary to obtain the value or manipulate the exception object created by the throw expression.
catch (int) {
}
// or
catch (int i) {
}
By default it is a pass-by-value parameter, but can be changed to reference declaration. The benefits are:

If no catch clause capable of handling the exception exists, program execution resumes in the function terminate() defined in C++ standard library, which default behavior is to call abort().


Exception specification list the exceptions a function may throw with the function declaration. It guarantees that the function does not throw any other types of exceptions. If in function declaration specifies an exception specification, redeclaration of the same function must specify an exception specification with the same types. The exception specifications on different declarations of the same function are not cumulative.
returntype1 Function1(parametertype1 parameter) throw(string);
// error: exception specification omitted
returntype1 Function1(parametertype1 parameter)
{
  // ...
}

class ClassName {
public:
  void SetMember1(member1type member1) throw(InvalidParamException);

protected:
  member1type member1_;
};
An empty exception specification guarantees that the function does not throw any exception.
returntype1 Function2(parametertype1 parameter) throw();
No type conversion is allowed between the type of the exception thrown and a type specified by the exception specification.
returntype1 Function1(parametertype1 parameter) throw(string)
{
  if (error)
    throw "Error!"; // run-time error: no const char* to string conversion
}
There is a small exception to this rule: when the exception specification specifies a class type or a pointer to a class type. If an exception specification specifies a class, then the function may throw exception objects of a class publicly derived from the class type in the exception specification. Similarly for pointers, if an exception specification specifies a pointer to a class, the function may throw exception objects that are pointers to a class publicly derived from this class type.
class MathException : public Exception { };

returntype1 Function1(parametertype1 parameter) throw(Exception)
{
  if (error)
    throw MathException;
}

If the function throws exception that is not listed in its exception specification (including the case that no conversion allowed) and does not handles the exception before it "escapes" outside the function, the compiler does not generate compile-time errors because this violation can be detected only at run-time (program encounters any exception can only known at run-time). Instead, the compiler generates code that if the violation occurs, function unexpected(), defined in the C++ standard run-time library, is invoked. Its default behavior is to call terminate().


try {
  // possible throw type Exception1
} catch (Exception1) {
  // ...
}
// ...
try {
  // possible throw type Exception2
} catch (Exception2) {
  // ...
}
Organization intermixes the handling of the exceptions with the normal processing of the program is not ideal. After all, exceptions are program anomalies that occur only in exceptional cases. Strategy that separate the code handles the program anomalies from the code that implements normal execution makes the code easier to follow and easier to maintain.
try {
  // possible throw type Exception1 and Exception2
} catch (Exception1) {
  // ...
} catch (Exception2) {
  // ...
}	
Function try block is function that its entire body is contained within the try block. This organization supports the cleanest separation between normal processing code and exception handling code.
int main()
try {
  // ...
} catch (Exception1) {
  // ...
} catch (Exception2) {
  // ...
}	

Inheritance for exception
class Exception {
public:
  static void print(string msg) const { cerr << msg << endl; }
}
class MathException : public Exception { };
class DivideByZeroException : public MathException {
  // ...
}
Because the exception object is created by copying the value of the throw expression, the exception thrown always has the exact type of the expression specified on the throw expression.
double Divide(int dividend, int divisor)
{
  if (divisor == 0)
  {
    DivideByZeroException de(dividend, divisor);
    MathException *pme = &de;
    throw *pme; // exception object is type MathExecption
  }
  else
    return dividend/(double)divisor;
}
The catch clause for the derived exception class must appear first. This ensures that the catch clause for the base class is only entered if no other catch clause applies. User of a class library may choose the level of granularity with which their applications will deal with the exceptions thrown from the library.
try {
  // ...
} catch (DivideByZeroException e) {
  cerr << "Try to divide " << e.GetDividend() << " by "
       << e.GetDivisor() << endl;
} catch (Exception e) { // no need to deal with MathException
  Exception::print("An exception encountered");
}	
By default, the catch clause parameter resembles a pass-by-value parameter. It creates its own local copy which is initialized with base class subobject of the actual derived class object. This copy is only accessed within the catch clause and destroyed end of the clause. If rethrown is the original exception object, not the base class type local object. Recall also virtual function only work for reference or pointer to base class.
class Exception {
public:
  virtual void print(void) const { cerr << "An exception encountered" << endl; }
}
class MathException : public Exception { };
class DivideByZeroException : public MathException {
public:
  virtual void print(void) const { cerr << "Try to divide by xero" << endl; }
}

// usage in application
try {
  // throw DivideByZeroException
} catch (Exception e) {
  e.print(); // call Exception::print(void)
  throw; // rethrow DivideByZeroException object
} // destroy local Exception object, but not DivideByZeroException object
If it is changed to a reference declaration to refer directly to the derived class exception object created by the throw expression (often for efficiency), virtual function will work.
try {
  // throw DivideByZeroException
} catch (const Exception& e) {
  e.print(); // call DivideByZeroException::print(void)
  throw; // rethrow DivideByZeroException object
} // no local Exception object to destroy
A virtual function in a base class may have an exception specification that differs from the exception specification of the member function that overrides it in a derived class. However, the exception specification of the derived class virtual function must be either equally or more restrictive than the exception specification of the base class virtual function. This ensures that when the derived virtual function is called through a pointer to a base class type, the call is guaranteed not to violate the exception specification of the base class member function.
class BaseName {
public:
  virtual double F1(double) throw ();
  virtual int F2(int) throw (int);
  virtual string F3(void) throw (int, string);
};
class DerivedName : public BaseName {
public:
  // error: exception specification less restrictive than BaseName::F1()
  double F1(double) throw (string);
  // ok: same exception specification as BaseName::F2()
  int F2(int) throw (int);
  // ok: derived F3() is more restrictive
  string F3(void) throw (int);
};
Function try block becomes necessary with class constructor, because normal try block inside the function body does not enclose the member initialization list to catch.
ClassName::ClassName(const char* name, double cent)
  : dollar_(Divide(cent, CentPerDollar)) // may throw DivideByZeroException
try {
  name_ = new char[strlen(name)+1];
} catch (DivideByZeroException) { // only possible using function try block
  // ...
} catch (std::bad_alloc) { // try block inside function body can handle
  // ...
}

C++ exception handling is nonresumptive; it doesn't provide a primitive for returning to the point from which an exception was thrown and continuing execution from there. If want to check to see whether can fix a problem before throwing an exception, call a function that checks and then throws only if the problem cannot be dealt with locally, for example new_handler.

Basically, someone resuming from an exception handler can never be sure that the code after the point of throw was written to deal with the excecution just continuing as if nothing had happened. An exception handler cannot know how much context to "get right" before resuming. To get such code right, the writer of the throw and the writer of the catch need intimate knowledge of each others code and context. This creates a complicated mutual dependency that wherever it has been allowed has led to serious maintenance problems.


A throw expression behaves somewhat like a function call and the catch clause behaves somewhat like a function definition. The main difference between these exception handling and function call is that all the information necessary to set up a function call is available at compile-time. But exception handling requires run-time support. Compiler does not know for a particular throw expression in which function the catch clause resides and where execution resumes after the exception has been handled. These decisions happen at run-time. The compiler cannot inform users when no handler exists for an exception. This is why the terminate() function exists: it is a run-time mechanism to tell users when no handler matches the exception thrown.


Throwing exception is not as fast as a normal function call. Exception handling is usually used to communicate program anomalies between parts of the program that are developed independently (for example throw from library layer and catch on user program). Error handling locally inside library may be better using error code. Exceptions are part of a library's interface and deciding which exceptions the library throws is an important phase of the library design.

Not all programs must catch exceptions thrown by libraries. Handling exception is useful when the user of a library cannot afford to crash, it gives the caller the choice as to which action should be taken when no meaningful action can be taken within the library code itself.


C++ standard library provides an exception class hierarchy. The exception classes are used to report program anomalies encountered during the execution of the functions in the C++ standard library and can be used in programs also. It is in <exception>. Include <stdexcept> to use them.
namespace std {

class exception {
public:
  exception(void) throw();
  exception(const exception&) throw();
  exception& operator=(const exception&) throw();
  virtual ~exception(void) throw();
  virtual const char* what(void) const throw();
};

}

Since default constructor, copy constructor, copy assignment operator and destructor are public, any program can freely create, copy and assign exception objects. Virtual destructor facilitates the definition of classes further derived from the class. Virtual what() provide textual description of the exception thrown and for overriding. Empty exception specification guarantees that the member function does not throw any exception again.

Errors are divided into two broad categories:
  1. logic error - due to the internal logic of programs. Logic errors are presumably preventable errors that are detectable before the program starts executing.
    namespace std {
    
    class logic_error : public exception {
    public:
      explicit logic_error(const string& what_arg);
    };
    class invalid_argument : public logic_error {
    public:
      explicit invalid_argument(const string& what_arg);
    };
    // receive argument that is not in the expected range of values
    class out_of_range : public logic_error {
    public:
      explicit out_of_range(const string& what_arg);
    };
    // attempt to produce object with length that exceeds its
    // maximal allowable size
    class length_error : public logic_error {
    public:
      explicit length_error(const string& what_arg);
    };
    class domain_error : public logic_error {
    public:
      explicit domain_error(const string& what_arg);
    };
    
    }
    
  2. run-time error - due to an event beyond the scope of the program. A run-time error is presumably detectable only while the program is executing.
    namespace std {
    
    class runtime_error : public exception {
    public:
      explicit runtime_error(const string& what_arg);
    };
    // range error in internal computation
    class range_error : public runtime_error {
    public:
      explicit range_error(const string& what_arg);
    };
    // arithmetic overflow and underflow error
    class overflow_error : public runtime_error {
    public:
      explicit overflow_error(const string& what_arg);
    };
    class underflow_error : public runtime_error {
    public:
      explicit underflow_error(const string& what_arg);
    };
    
    }
    
The class exception is also the base class of the bad_alloc exception thrown by operator new when it fails to allocate the requested and bad_cast thrown when a reference dynamic_cast fails.
namespace std {

class bad_alloc : public exception {
   // ...
public:
  bad_alloc(void) throw();
  bad_alloc(const bad_alloc&) throw();
  bad_alloc & operator=(const bad_alloc&) throw();
  virtual ~bad_alloc(void) throw();
  virtual const char* what(void) const throw();
};

}
Index