I have an exception class:
class MyException : public std::exception
{
public:
MyException( char* message )
: message_( message )
{
if( !message_ ) throw std::invalid_argument("message param must not be null");
}
};
And at my throw site:
try {
throw MyException( NULL );
}
catch( std::exception const& e ) {
std::cout << e.what();
}
(code was not compiled, so please excuse any errors)
I'm wondering what will happen when I throw from a constructor while constructing due to another throw. I assume this is legal, and the catch will end up catching a std::invalid_argument, and the previous exception thrown (MyException) will be ignored or cancelled out.
My goal with this design is to enforce invariants in my exception class. message_ should never be NULL, and I don't want to have if conditions to check if it is null in my what() overload, so I check them in the constructor and throw if they are invalid.
Is this correct, or is the behavior different?
The object you intend to throw (in this case MyException) must be successfully constructed before it can be thrown. So you're not throwing it yet, since it hasn't been constructed.
So this will work, throwing the exception from within MyException's constructor. You won't trigger the "throwing an exception while handling an exception causes std::terminate" issue.
If the exception handling mechanism, after completing evaluation of the expression to be thrown but before the exception is caught, calls a function that exits via an exception, std::terminate is called (15.5.1).
This means that until the constructor (of the object being thrown in this case) completes nothing special is going to happen. But after the constructor completes any other uncought exception will result in terminate() being called.
The standard goes on to provide an example:
struct C
{
C() { }
C(const C&) { throw 0; }
};
int main()
{
try
{
throw C(); // calls std::terminate()
}
catch(C) { }
}
Here terminate is called because the object is first created. But then the copy construction is called to copy the exception to the holding location (15.1.4). During this function call (copy construction) an uncaught exception is generated and thus terminate is called.
So your code as shown should work as expected.
MyException is generated with a good message and thrownstd::invalid_argument is generated and thrownIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With