views:

261

answers:

2

Hello all :)

I'd like to encapsulate Win32 errors (those returned from GetLastError()) in some form of exception class. Rather than having a single Win32 exception, however, I'd like to be able to have a specialized exception catchable for common errors, such as ERROR_ACCESS_DENIED.

For example, I'd have classes declared like this:

class WindowsException : public std::exception
{
public:
    static WindowsException Create(DWORD lastError);
    //blah

};

class ErrorAccessDeniedException : public WindowsException
{
public:
    //blah
};

However, I'd like the Win32 exception to be responsible for picking the right exception to return. That is, the thrower of the exception should look like:

int DangerousMethod() {
    throw WindowsAPI::WindowsException::Create(GetLastError());
}

and the catcher might look like:

try
{
    DangerousMethod();
} catch(WindowsAPI::ErrorAccessDeniedException ex)
{
    //Code for handling ERROR_ACCESS_DENIED
} catch(WindowsAPI::WindowsException ex)
{
    //Code for handling other kinds of error cases.
}

My problem is that if the WindowsException::Create factory method returns a WindowsException, then the subtype (potentially ErrorAccessDeniedException) is sliced down to the base type. That is, the instance can't be polymorphic. I don't want to use a new'd pointer, because that would force the exception handler to delete it when it's done.

Does anyone know of a design solution that would be feasible for solving this problem elegantly?

Billy3

+9  A: 

Change

int DangerousMethod() {
    throw WindowsAPI::WindowsException::Create(GetLastError());
}

To

int DangerousMethod() {
    WindowsAPI::WindowsException::Throw(GetLastError());
}

Meaning, instead of returning the exception then throwing it (which will slice, as you observed), have your helper/factory method throw it directly.

Terry Mahaffey
... DUH BILL :) Thank you very much.
Billy ONeal
As I was reading the question I was inventing a convoluted solution where a static instance of every possible exception was maintained by the framework. Terry's solution is only "DUH Obvious" once you've seen it. (Either that, or we're both stupid :-)
Andrew Shepherd
What's wrong with `WindowsAPI::WindowsException::Throw()` and letting that function call `GetLastError()`?
sbi
You could -- I used the explicit GetLastError() in my example code to make it more clear what I wanted to do.
Billy ONeal
@Billy: That's a good point.
sbi
A: 

Some more exception handling background reading: http://www.informit.com/articles/article.aspx?p=373339

A note on type slicing and rethrowing:

When rethrowing an exception e , prefer writing just throw; instead of throw e; because the first form always preserves polymorphism of the rethrown object.

Igor Zevaka
Not saying that's bad information, but ... what does that have to do with my question?
Billy ONeal
Just alerting to more possible slicing issues with exception handling.
Igor Zevaka