Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: How to catch exceptions thrown from constructors?

Tags:

c++

exception

I have a class, call it A, whose constructor takes some input arguments, and may throw an exception if they are incompatible for constructing that object. In my main code, I construct an object of type A as follows:

A my_obj(arg1,arg2,arg3);

and use it. Obviously if the constructor fails and throws the exception, the execution of the program will be terminated after printing out an 'unhandled exception' message.

I, however, would like to give the user more information in this case and tell him/her why the exception has been thrown. So, I need a way to catch the exception.

To this end, one possibility is to enclose the whole code, starting from the declaration of my_obj till the end of the program in a try block and catch the exception afterwards:

try {
    A my_obj(arg1, arg2, arg3);
    // ... 
    // about 100 other lines of code being executed if my_obj is created properly 
}
catch (std::exception& e) {
    // print a user-friendly error message and exit
}

But this looks to me a bit of an 'overkill'. Specifically since no other exceptions are thrown in the remaining 100 lines. Is there any other nicer way to accomplish this?

like image 264
MikeL Avatar asked Oct 19 '25 09:10

MikeL


2 Answers

If the constructor throws, you don't have an object. std::optional<> is a type that means "We might not have an object here".

template <typename T, typename ... Args>
std::optional<T> try_make(Args&& ... args)
{ try {
    return make_optional(std::forward(args...));
} catch (...) {
    return {};
} }

Then

auto my_obj = try_make<A>(arg1,arg2,arg3);
if (my_obj) {
    // about 100 other lines of code being executed if my_obj is created properly
}
like image 69
Caleth Avatar answered Oct 21 '25 23:10

Caleth


One possibility would be the usage of a pointer (better use a smart pointer such as an unique_ptr as in below code). You would leave the unique_ptr empty, call the constructor in the try block and move the pointer into the unique_ptr. After that your other code executes. Surely you have to check for a valid pointer with the operator bool of unique_ptr in a simple if statement.
To simplify the usage of my_obj a reference is taken: A& my_obj_ref = *my_obj;.

std::unique_ptr<A> my_obj;
try {
    my_obj = std::move(std::unique_ptr<A>(new A(arg1, arg2, arg3));
}
catch (std::exception& e) {
    // print a user-friendly error message and exit
}

if (my_obj) { // needed if your exception handling doesn't break out of the function
    A& my_obj_ref = *my_obj;

    // ... 
    // about 100 other lines of code being executed if my_obj is created properly
}

Remember that this way would allocate your object on the heap instead of the stack.

like image 38
Andre Kampling Avatar answered Oct 21 '25 22:10

Andre Kampling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!