hiddensunset4
hiddensunset4

Reputation: 6029

Optional Error Handling

I have a create method as shown below, in which I want to (if the return is a null pointer) get the error from. However I want this error handling to be optional, and not a requirement in calling the function.

The code:

class foo {
    foo() {...};
public:
    ~foo();
    static foo* createFoo(int aparam = 42, int bparam = 10, int& error = ?) {
        afoo* = new foo();
        if (!afoo) {
            error = 11;
            return 0; //NULL
        }
        ...
        return afoo;
    }

}

So I can then decide to either use:

foo* myfoo = createFoo(42);
if (!myfoo) { ... }

Or

int errorcode = 0;
foo* myfoo = createFoo(42, 10, errorcode);
...

At this point (in my real code), I am just using a null pointer (instead of a ref) and determining its validity in the createFoo code before giving it error.

My interest is in the best practice for this situation.

Upvotes: 2

Views: 367

Answers (2)

Marc Butler
Marc Butler

Reputation: 1376

I don't know that I can offer best practice but here is my perspective.

Checking for NULL (a failed allocation) is standard practice in C and C++, it is a well understood and easily recognized idiom. The addition of an optional error code, while providing flexibility also adds arguably unneeded complexity. It burdens the caller to decide whether they will use the parameter.

Why would they use the parameter unless they felt it was likely to fail in that location? How would

If you feel the error code is significant. I would suggest the alternate signature, whereby you always check the return code, and do not check the value of the returned pointer:

// Returns error code.
static int createFoo(int, int, Foo **);

This is a perhaps less convenient function, but nudges the caller (user) in the right direction.

Alternately, you could use exceptions, either ensuring std::bad_alloc is thrown, or throwing an exception of your own creation with the appropriate error code. This would seem to be the cleanest signature:

struct fooException { int error; }

// Throws fooException if cannot create foo.
static foo * createFoo(int, int);

The philosophy I am driving at is: minimize complexity. In this case by removing what seems to be an extraneous option. Either the error code is significant and should always be used, or it extraneous and will always be ignored.

Upvotes: 1

Nathanael
Nathanael

Reputation: 1772

When you pass something by reference, you are telling the user of that function that this is a required parameter. If you want to make the error code optional, pass in a pointer to an int and set its default value to null.

static foo* createFoo(int aparam = 42, int bparam = 10, int* error = NULL)

Upvotes: 1

Related Questions