DrTarr
DrTarr

Reputation: 952

Returning a class in a function with exception handling

Let's say I have function that is mean to return a class, however, I wish to use exception handling when calling the constructor. Issue is, in the case of an exception the class I wanted to return is out of scope and I have nothing to return:

myclass GetClass() {
    try {
        myclass classtoreturn(7);
        return classtoreturn;
    } catch ( const std::exception& ex ) {
        //
    } catch ( const std::string& str ) {
        //
    } catch (...) {
        //
    }

    return ??;
}

However, if I declare the class outside of the try/catch, I'm going to have the issue of an un-initialized class to return:

myclass GetClass() {
    myclass classtoreturn;
    try {
        classtoreturn(7);
        return classtoreturn;
    } catch ( const std::exception& ex ) {
        //
    } catch ( const std::string& str ) {
        //
    } catch (...) {
        //
    }

    return classtoreturn;   //Unitialized!
}

My first instict was to return a pointer instead and return a NULL pointer in the event of an exception, but then the pointer would be pointing to an out of scope class which still is no good. Seems like this would be a common issue but I haven't stumbled upon a solution.

Also, the actual application can be seen here, where I am trying to return the gpsmm class to my main function so it can be later passed as a pointer to a polling function.

Thanks!


OK, reading some responses now I'm thinking it makes sense to catch the exception at the caller, however, I think this just propogates the issue to the caller:

void main() {
    try{
        myclass classforuse{ GetClass() };
    } catch (...) {
        //
    }

    //Want to do something with "classforuse" but it's out of scope!
}

As I understand it the class will beconstructed when I declare it, so there's no way for me to construct a class from within a try{} and then use it outside the scope of that same try{} without using std/boost::optional. Is that correct? I think the boost libraries will be my only option unless I find a practical means to use the class from within the same try{}. Thanks

Upvotes: 1

Views: 515

Answers (3)

AMA
AMA

Reputation: 4214

The catch looks misplaced. Consider catching exceptions in the client code or re-throwing. Otherwise, the function should be able to recover and return a successfully created object.

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180630

There are few ways you could handle this. The first is to change the return the return type of the function and instead of returning the class by value pass it by std::unique_ptr. std::unique_ptr can be null so if there is an exception you can return a null unique_ptr otherwise you just return the unique_ptr to the object you created.

The other option is to use boost::optional or std::optional. You can use boost::optional right now but std::optional is a C++17 feature so it's availability is limited. Personally I like the optional approach better as it more describes the situation just by its type. optional also has the additional benefit that there is no dynamic memory allocation.

Lastly you could not recover and have the function throw. This will signal to the caller that something happened and they did not get an object returned.

Upvotes: 2

François Andrieux
François Andrieux

Reputation: 29022

My understanding of your question is that, in the event of an exception, your function is not able to fulfill it's obligation to return a valid myclass object and you are not sure how to handle it. The first solution to throw an exception, perhaps the one that caused it to fail. While inside a catch block, you can use an empty throw; statement to rethrow the same exception.

catch(const std::exception & err) {
    // do whatever it is you need to do (logging?)
    throw; // this statement throws 'err' again
}

I don't know if you expect to do anything with those exceptions (your catch blocks are empty, but it might be for brevity) but normally, if you can't fix the problem here, don't try to catch the exception. Just remove the whole try/catch and let the exception propagate.

If throwing from your function isn't acceptable for your case then you will have to change your function to return something other than myclass. If you have access to C++17 consider using std::optional or a similar wrapper.

Upvotes: 1

Related Questions