Reputation: 952
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
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
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
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