Though i prefer a proper class hiearachy for exception handling . But this one also an interesting one.
I need 4 class to explain tis , we can take few less or more then i take.
one enum type we declare which contains the exception type like SUCCESS ,FAILURE ,LOGINFAILURE etc.
Just define this in a .h file called ExceptionType.h
These are the contentent of this ExceptionType.h file
enum ExceptionType
{
SUCCESS = 0, // apps execution is success
LOGINFAIL = 101, // Login Failed
FAIL, // Failed executing
UNKNOWN // Unknown Exception
};
Now we will discuss one more container class (this will map all the exception which we have defined in exceptionType.h)
example
Let say this container class called EnumString.h
// Local Headers
#include "ExceptionType.h"
using namespace std;
// Class Definition
template < class T >
class EnumString
{
public:
// Default Constructor
EnumString< T >();
// Destructor
~EnumString< T >() {}
// Explicit Constructor
explicit EnumString< T >( const T value );// Get method for retreiving value
const T getValue() const
{
return _value;
}
// Get method for retreiving Name
const string& getName() const
{
return _stringMap[_value];
}
// Class Name retrieval method
static const char* className() { return "EnumString"; }
private:
// Method to Container
static void populate();
// Method to set Unknown Exception value into container
static void setUnknownValue();
// Method to get Unknown Exception value from container
static T getUnknownValue();
T _value; // Enum type value
static map< T, string, less< T > > _stringMap;// Container for Enum types
};
template < class T >
map< T, string, less< T > > EnumString< T >::_stringMap;
// Default Constructor
template '<' class T'>'
EnumString'<'T'>'::EnumString()
{
// Do Nothing
}
template '<'class T'>'
EnumString'<'T'>'::EnumString( const T value ) : _value(value)
{
// Check for container empty
if ( _stringMap.size() == 0 )
{
populate();
}
// Check Exception is present in Container
if ( _stringMap.find(value) == _stringMap.end() )
{
// This can occur if the Exception is not defined in the
// omexcpdefs.h and that is thrown from the application
// For this case set "UnKnown Exception" into Container
// And into the KeyType value
_value = getUnknownValue();
setUnknownValue();
}
} // end of EnumString'<'T'>'::EnumString()
template '<'class T'>'
EnumString'<'T'>'::EnumString( const T value ) : _value(value)
{
// Check for container empty
if ( _stringMap.size() == 0 )
{
populate();
}
// Check Exception is present in Container
if ( _stringMap.find(value) == _stringMap.end() )
{
// This can occur if the Exception is not defined in the
// omexcpdefs.h and that is thrown from the application
// For this case set "UnKnown Exception" into Container
// And into the KeyType value
_value = getUnknownValue();
setUnknownValue();
}
} // end of EnumString'<'T'>'::EnumString()
template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::populate()
{
// Add all the Known exceptions
_stringMap[SUCCESS] = " SUCCESS DONE";
_stringMap[LOGINFAIL] = " LOGIN FAILED";
_stringMap[FAIL] = " EXECUTION FAILED";
} // end of EnumString
template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::setUnknownValue()
{
// Update Unknown exceptions
_stringMap[UNKNOWN] = " UNKNOWN ERROR";
} // end of EnumString'<'ExceptionType'>'::setUnknownValue()
template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::setUnknownValue()
{
// Update Unknown exceptions
_stringMap[UNKNOWN] = "UNKNOWN ERROR";
} // end of EnumString'<'ExceptionType'>'::setUnknownValue()
Now I have defined the container class , this class actually maped the error and all thye stufs...
Now i will define a class which will have a data member of type this container class. This class i have defined for one more level
of indirection.
lets define the class as MyException. and the file name MyException.h
#ifndef MYEXCEPTION_H
#define MYEXCEPTION_H
#include "EnumString.h"
// Class Definition
template '<'class T'>'
class MyException
{
public:
// Default Constructor
MyException < T >();
// Destructor
~MyException'<'T'>'() {}
// Explicit Constructor
explicit MyException
private:
protected:
EnumString < T > _ExpMap;
};
// Default constructor
template '<'class T'>'
MyException'<'T''>'::MyException()
{
// Do Nothing
}
#endif /* MYEXCEPTION_H */
Then I will define the application class where i will use this , I mean inherit this MyException class .Just have a look
#ifndef APPEXCEPTION_H
#define APPEXCEPTION_H
#include "ExceptionType.h"
#include "MyException.h"
#include
// Class Definition
class AppException : public MyException
{
public:
// Default Constructor
AppException() {}
// Destructor
~AppException() {}
// Explicit Constructor
explicit AppException( ExceptionType expNum )
: MyException
{
}
// Method to get Exception Description
const string& getExpName() const
{
return ( _ExpMap.getName() );
}
// Class Name retrieval method
const char* className() { return "AppException"; }
};
#endif /* APPEXCEPTION_H */
So if i want to through an exception of particular type, Just create the object of this type and through it.
Below the unit test code
#include
#include "MyException.h"
#include "appException.h"
int main()
{
for ( int i=0; i != 4; i++ )
{
try
{
if ( i == 0 )
throw AppException(SUCCESS);
if ( i == 1 )
throw AppException(LOGINFAIL);
if ( i == 2 )
throw AppException(FAIL);
if ( i == 3 )
throw AppException((ExceptionType)300);
}
catch ( AppException &exp )
{
cout << "Caught Exception: "'< <' exp.getExpName() << endl;
}
}
return ( 0 );
}