I wrote my own exception class, deriving from std::runtime_error
to have Error-IDs, timestamps and inner exceptions.
It seems to work, but are there any drawbacks?
The only thing I see is the deep-copy in the copy-constructor, which is not efficient, when there are many nested exceptions. But exceptions should be rare and not be nested too much, so I think it's a downside I can cope with.
#pragma once
#include <stdexcept>
#include <string>
#include <sstream>
#include <time.h>
#include <memory>
class MyException : public std::runtime_error
{
public:
MyException(const MyException& exception)
: std::runtime_error(exception.what()),
exceptionId(exception.id()),
ts(exception.timestamp()),
innerException(NULL)
{
if (exception.inner() != NULL)
{
innerException = new MyException(*exception.inner());
}
else
{
innerException == NULL;
}
}
MyException(const std::string& _Message)
: std::runtime_error(_Message),
exceptionId(0),
innerException(NULL)
{
time(&ts);
}
MyException(const std::string& _Message, unsigned int id)
: std::runtime_error(_Message),
exceptionId(id),
innerException(NULL)
{
time(&ts);
}
MyException(const std::string& _Message, unsigned int id, MyException* innerException)
: std::runtime_error(_Message),
exceptionId(id),
innerException(new MyException(*innerException))
{
time(&ts);
}
virtual ~MyException()
{
delete innerException;
}
unsigned int id() const { return exceptionId; }
time_t timestamp() const { return ts; }
const MyException* inner() const { return innerException; }
private:
unsigned int exceptionId;
time_t ts;
const MyException* innerException;
};
This is how I would use it:
void handleException(MyException *ex)
{
cout << "exception " << ex->id() << " - " << ex->what() << endl;
const MyException* innerException = ex->inner();
int t = 1;
while (innerException != NULL)
{
for (int i=0; i<t; ++i)
{
cout << "\t";
}
++t;
cout << "inner exception " << innerException->id() << " - " << innerException->what() << endl;
innerException = innerException->inner();
}
}
void throwRecursive(int temp)
{
if (temp == 0)
{
throw runtime_error("std::runtime_error");
}
try
{
throwRecursive(--temp);
}
catch (MyException &ex)
{
throw MyException("MyException", (temp+1), &ex);
}
catch (exception &ex)
{
throw MyException(ex.what(), (temp+1));
}
}
void myExceptionTest()
{
try
{
throwRecursive(3);
}
catch (MyException &ex)
{
handleException(&ex);
}
}
And the output:
exception 3 - MyException
inner exception 2 - MyException
inner exception 1 - std::runtime_error