c++ - c++ throw exception of class type

There are something in exception handling that is not easy apprehensible for most readers, so here is the discussion on some specific of the exception handlings.

 

the code that the example below will use to illustrate is as follow. 

 

 

#include <iostream>
#include <string>
using std::cout;
using std::cerr;
using std::endl;
using std::string;


class Excp 
{
public : 
	// print error message
	static void print(string msg) { 
		cerr << msg << endl;
	}
};

class popOnEmpty : public Excp { };
class pushOnFull: public Excp {
public:
	pushOnFull(int value ) {} ;
};

class iStack { 
public:
	void push(int value);
	bool full() { return true ; } 
};

 

 

so suppose that we have a throw expression as follow. 

 

void iStack::push(int value)
{
	if (full() ) 
	{
		// value stored in exception object 
		throw pushOnFull(value);
	}
}

 

 there are actually a lots of things happening underneath.

 

many stap take place as a consequence of executing this throw exception 

 

  1. the throw exception creates a temporary object of class type pushOnFull by calling the class constructor
  2. An exception object of type pushOnFull is created to be passed to the exception handler. The exception object is is a copy of the temporary object created by the throw expression in step 1. it is created by calling the calss pushOnfull's copy constructor
  3. the temporary object created by the throw expression in step 1 is destroyed byfore the search for a handler starts.

why the exception object is necessary

 you may wonder why the step 2 is needed and why an expression object is created -  

 

 
   the expression 
      pushOnFull(value);
 

 create a temporary boject that is destroyed at the end of throw expression. The exception, however must last until a handler has been found, which may be many functions further up the chain 

 of the function calls. It is therefore necessary to copy the temporary object into a storage location, called the exception object, that is guaranteed to last until the exception hass ben handled

 

 however, this a classic way how how an exception is constructed, but in some cases it may be possible for the implementation to create the exception object directly, without creating the temporary object in step 1,  however, this temporary elinimation is not required or always possible. 

 

another  tripwire/pitfall/trap that people falls is when handling exception when pointer is concerned. 

 

here is the code. 

 

void iStack::push(int value) 
{
	if (full()) { 
		pushOnFull except(value);

		Excp *pse = &except;
		throw *pse; // exception object has type Excp
	}
}

 

 because of the discussion we had before, since the dereference will return the type of object what the pionter points to, so the return value is of type Excp... even though the pointer actually   point to a more derived class object , the actualy type is not examined to create the exception object

 

restriction on the class that serve as a exception object

 

 the implied restriction on the kind of classes that can be used to create exception objects, the throw exception in the iStack member function push() is in error if 

  1. the class pushOnFull does not have a constructor that accepts an arguments of type int or if this constructor is not accessible
  2. the class pushOnFull has neither a copy constructor  or the constructor is not acceesible 
  3. the class pushOnFull is an abstract base class, because a program cannot create an object of an abstract class type . 

你可能感兴趣的:(C++)