I'm a student in my first C++ programming class, and I'm working on a project where we have to create multiple custom exception classes, and then in one of our event handlers, use a try/catch
block to handle them appropriately.
My question is: How do I catch my multiple custom exceptions in my try/catch
block? GetMessage()
is a custom method in my exception classes that returns the exception explanation as a std::string
. Below I've included all the relevant code from my project.
Thanks for your help!
try/catch block
// This is in one of my event handlers, newEnd is a wxTextCtrl
try {
first.ValidateData();
newEndT = first.ComputeEndTime();
*newEnd << newEndT;
}
catch (// don't know what do to here) {
wxMessageBox(_(e.GetMessage()),
_("Something Went Wrong!"),
wxOK | wxICON_INFORMATION, this);;
}
ValidateData() Method
void Time::ValidateData()
{
int startHours, startMins, endHours, endMins;
startHours = startTime / MINUTES_TO_HOURS;
startMins = startTime % MINUTES_TO_HOURS;
endHours = endTime / MINUTES_TO_HOURS;
endMins = endTime % MINUTES_TO_HOURS;
if (!(startHours <= HOURS_MAX && startHours >= HOURS_MIN))
throw new HourOutOfRangeException("Beginning Time Hour Out of Range!");
if (!(endHours <= HOURS_MAX && endHours >= HOURS_MIN))
throw new HourOutOfRangeException("Ending Time Hour Out of Range!");
if (!(startMins <= MINUTE_MAX && startMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Starting Time Minute Out of Range!");
if (!(endMins <= MINUTE_MAX && endMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Ending Time Minute Out of Range!");
if(!(timeDifference <= P_MAX && timeDifference >= P_MIN))
throw new PercentageOutOfRangeException("Percentage Change Out of Range!");
if (!(startTime < endTime))
throw new StartEndException("Start Time Cannot Be Less Than End Time!");
}
Just one of my custom exception classes, the others have the same structure as this one
class HourOutOfRangeException
{
public:
// param constructor
// initializes message to passed paramater
// preconditions - param will be a string
// postconditions - message will be initialized
// params a string
// no return type
HourOutOfRangeException(string pMessage) : message(pMessage) {}
// GetMessage is getter for var message
// params none
// preconditions - none
// postconditions - none
// returns string
string GetMessage() { return message; }
// destructor
~HourOutOfRangeException() {}
private:
string message;
};
Derive all of your exceptions from a common base class
BaseException
that has a virtual methodGetMessage()
.Then
catch(const BaseException& e)
.If you have multiple exception types, and assuming there's a hierarchy of exceptions (and all derived publicly from some subclass of
std::exception
,) start from the most specific and continue to more general:On the other hand, if you are interested in just the error message -
throw
same exception, saystd::runtime_error
with different messages, and thencatch
that:Also remember - throw by value, catch by [const] reference.
You should create a base exception class and have all of your specific exceptions derive from it:
You can then catch all of them in a single catch block:
If you want to be able to call
GetMessage
, you'll need to either:BaseException
, orGetMessage
a virtual member function inBaseException
and override it in each of the derived exception classes.You might also consider having your exceptions derive from one of the standard library exceptions, like
std::runtime_error
and use the idiomaticwhat()
member function instead ofGetMessage()
.I run into the same problem and here is what I ended up with:
In my case the function returns when it doesn't get an exception. So I don't actually have to do anything inside the catch but can do the work outside the try.
I had a similar problem today, but it turned out I didn't need my solution to solve my problem. Honestly, I couldn't think of real use cases (logging?), and I didn't find much use for it in my code.
Anyway, this is an approach with type lists (requires C++11). I think the advantage of this approach is that there's no need to have a common base class for custom exceptions (except for std::exception, maybe?). In other words, it is not intrusive to your exception hierarchy.
There might be some subtle errors that I am not aware of.