C++ constructor initializer list throw exceptions - c++

I have a problem with the following code. As we can see I have already handled the exception thrown by A's constructor in C's constructor, why should I bother to catch and handle the exception again in the main function?
#include <iostream>
class WException : public std::exception
{
public:
WException( const char* info ) : std::exception(info){}
};
class A
{
public:
A( int a ) : a(a)
{
std::cout << "A's constructor run." << std::endl;
throw WException("A constructor throw exception.");
}
private:
int a;
};
class B
{
public:
B( int b ) : b(b)
{
std::cout << "B's constructor body run." << std::endl;
throw WException("B constructor throw exception");
}
private:
int b;
};
class C : public A, public B
{
public:
C( int a, int b ) try : A(a), B(b)
{
std::cout << "C's constructor run." << std::endl;
}
catch( const WException& e )
{
std::cerr << "In C's constructor" << e.what() << std::endl;
}
};
int main( int argc, char* argv[] )
{
try
{
C c( 10, 100 );
}
catch( const WException& e )
{
std::cerr << "In the main: " << e.what() << std::endl;
}
return 0;
}

You cannot actually catch an exception in a constructor. You can handle it, but you have to rethrow it or another exception. The reason is about object integrity and object lifetimes:
If the construction of a throws, a part of c has not been initialized and is completely missing - lifetime of a never starts. a is not an optional part of C, otherwise it had to be a pointer or a std::optional (since C++14 - boost::optional before that).
So how do you assemble a C if one of its vital parts cannot be constructed? You can't. c can never start to exist as a complete object, so there is no way you can exit the constructor normally. That's the reason why if construction of a member object fails, construction of the whole object has to fail, i.e. has to throw an exception.
If you don't throw an exception in C::C's catch block, the compiler will do so for you.
C++ Standard, §15.3,15:
The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.
For a broader treatment on that topic, see http://www.gotw.ca/gotw/066.htm

Related

How function-level exception handling works?

There is the following code, from here
class Base {
int i;
public:
class BaseExcept {};
Base(int i) : i(i) { throw BaseExcept(); }
};
class Derived : public Base {
public:
class DerivedExcept {
const char* msg;
public:
DerivedExcept(const char* msg) : msg(msg) {}
const char* what() const { return msg; }
};
Derived(int j) try : Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
};
int main() {
try {
Derived d(3);
}
catch (Derived::DerivedExcept& d) {
cout << d.what() << endl; // "Base subobject threw"
}
}
My question is, why the thrown exception is not caught here
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
But the catch in main?
catch (Derived::DerivedExcept& d) {
cout << d.what() << endl; // "Base subobject threw"
}
Why does it output "Base subobject threw"
According to my understanding, the thrown exception should be caught in the catch after try (or the function body equivalent to try), but there is no, why?
What is the propagation path of the exception?
code from there
My question is this, try catch I have seen before all have this form.
try{}
catch(){}
So I think for the following snippet
Derived(int j) try: Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
When Derived() throws an exception, it should be caught by the catch (BaseExcept&)in the following line, not by the catch (Derived::DerivedExcept& d) in the main function.
But when I comment out it here
catch (Derived::DerivedExcept& d) {
//cout << d.what() << endl; // "Base subobject threw"
}
There will be no "Base subobject threw" output.
This is different from what I expected. I am learning basic exception knowledge. Did I understand something wrong
Derived(int j) try : Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) { // why the thrown exception is not caught here
throw DerivedExcept("Base subobject threw");;
}
The only way for the program to output Base subobject threw is if the exception is actually caught where you do not think it's caught. The string does not exist anywhere else in the program.
But the catch in main?
That's because you throw an exception in the catch. That exception is not caught by the same catch (which would result in infinite recursion in this case). It's caught by the outer try..catch which you have in main.

How to catch exceptions from a constructors in C++

Suppose we have a constructor which may throw exceptions.
class A{
public:
A(); // may throw exceptions
};
And we can use this way to catch the exceptions:
try{
A a;
// do somethings to a, and I have to put everything about a here
}catch(...){
// handle exceptions
}
So my question is how to avoid putting everything in the try-catch block, without using a pointer.
You could define a creation function that handles the exception for you, with a sensible default value to return in case of an exception, for example:
struct A
{
A() : data("Default")
{
std::cout << "In A()" << std::endl;
}
A(const A& other) : data(other.data)
{
std::cout << "In A(A)" << std::endl;
}
A(bool param)
{
std::cout << "In A(bool)" << std::endl;
if(param)
throw std::runtime_error("Failed");
data = "Hello";
}
std::string data;
};
A createA(bool param, A& def_a)
try
{
return A(param);
}
catch (...) {
//...
return def_a;
}
Then you can initiate your actual A with the return value of this function. Due to RVO, no copy will be performed if the creation is successful, only if it fails (as it will have to then copy the default value):
int main(int argc, char**args)
{
A defA;
A a1 = createA(true, defA);
A a2 = createA(false, defA);
std::cout << "A1: " << a1.data << std::endl;
std::cout << "A2: " << a2.data << std::endl;
return 0;
}
The output of this is:
In A()
In A(bool)
In A(A)
In A(bool)
A1: Default
A2: Hello
The first constructor is the default value. Then you can see after the first A(bool) call (which throws), a copy constructor call is made to return the default value. The second call, which doesn't fail, has no copy constructor call (due to RVO). After this you end up with a default A and a successfully created A which you can use thereafter.
Of course, if the copy constructor can also throw, then you might have an exception escape createA - if this is the case you would have to modify this design somewhat.
One possible approach is to use a sentry.
class sentry {
public:
bool exception_thrown=true;
void constructed()
{
exception_thrown=false;
}
~sentry()
{
if (exception_thrown)
{
// Whatever you want to do
}
}
};
Then:
sentry a_sentry;
A a;
a_sentry.constructed();
In the sentry's destructor, if exception_thrown is set, it could only be because an exception was thrown in A's constructor, because the flag gets cleared immediately after A gets fully constructed. So, put the cleanup code in the destructor. One thing you have to be careful with this approach is that the destructor itself cannot throw an exception of its own.
You can then also do things like:
class A_with_sentry : public sentry, public A {
public:
A_with_sentry()
{
constructed();
}
};
Then just declare:
A_with_sentry a;
Then, go a step further, and make this a template function, have the constructor perfect-forward its variadic parameters to the sentried object's constructor, etc...
There is other way but not recommended because you need to deal with pointers.
A* a=nullptr;
try {
a = new A();
}
catch(...){
}
if(a){
//do somethings to a, and I have to put everything about a here
delete a;
}

RAII Failure - Why Does this C++ Code Leak? - throw in ctor in try block prevents dtor

The output of the program below is:
begin try
Object() ctor
begin catch
Why is the Holder class's destructor not called? Is this a memory leak? Is it possible to call the Holder class's destructor without rethrowing?
#include <iostream>
#include <exception>
class Object
{
public:
Object() { std::cout << "Object() ctor" << std::endl; }
~Object() { std::cout << "~Object() dtor" << std::endl; }
};
class Holder
{
public:
Holder() :myObjectP( new Object() )
{
throw std::exception();
}
~Holder()
{
std::cout << "~Holder()" << std::endl;
delete myObjectP;
}
private:
Object* myObjectP;
};
int main(int argc, char* argv[])
{
try
{
std::cout << "begin try" << std::endl;
Holder h;
}
catch ( ... )
{
std::cout << "begin catch" << std::endl;
}
return 0;
}
In this case, your Holder object h is not fully constructued, that is that h's constructor had not finished its construction before the stack unwinding process had begun.
C++11 15.2 Constructors and destructors
(2)
An object of any storage duration whose initialization or destruction
is terminated by an exception will have destructors executed for all
of its fully constructed subobjects (excluding the variant members of
a union-like class), that is, for subobjects for which the principal
constructor (12.6.2) has completed execution and the destructor has
not yet begun execution.

Call member's constructor in a Class constructor's try-catch block? [duplicate]

Here's a curious one. I have a class A. It has an item of class B, which I want to initialize in the constructor of A using an initializer list, like so:
class A {
public:
A(const B& b): mB(b) { };
private:
B mB;
};
Is there a way to catch exceptions that might be thrown by mB's copy-constructor while still using the initializer list method? Or would I have to initialize mB within the constructor's braces in order to have a try/catch?
Have a read of http://weseetips.wordpress.com/tag/exception-from-constructor-initializer-list/)
Edit: After more digging, these are called "Function try blocks".
I confess I didn't know this either until I went looking. You learn something every day! I don't know if this is an indictment of how little I get to use C++ these days, my lack of C++ knowledge, or the often Byzantine features that litter the language. Ah well - I still like it :)
To ensure people don't have to jump to another site, the syntax of a function try block for constructors turns out to be:
C::C()
try : init1(), ..., initn()
{
// Constructor
}
catch(...)
{
// Handle exception
}
It's not particularly pretty:
A::A(const B& b) try : mB(b)
{
// constructor stuff
}
catch (/* exception type */)
{
// handle the exception
}
I know it has been awhile since this discussion started. But that try-and-catch construct mentioned by Adam is part of the C++ standard and is supported by Microsoft VC++ and GNU C++.
Here is the program that works. By the way the the catch generates automatically another exception to signal about the constructor failure.
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class my_exception: public exception
{
string message;
public:
my_exception(const char* message1)
{
message = message1;
}
virtual const char* what() const throw()
{
cout << message << endl;
return message.c_str();
}
virtual ~my_exception() throw() {};
};
class E
{
public:
E(const char* message) { throw my_exception(message);}
};
class A
{
E p;
public:
A()
try :p("E failure")
{
cout << "A constructor" << endl;
}
catch (const exception& ex)
{
cout << "Inside A. Constructor failure: " << ex.what() << endl;
}
};
int main()
{
try
{
A z;
}
catch (const exception& ex)
{
cout << "In main. Constructor failure: " << ex.what() << endl;
}
return 0;
}
You could work with lazy initialization, though, that is hold a unique_ptr to Reader in MyClass and create it with new. That way, you do not even need the flag has_reader but you can just see if your unique_ptr is initial or not.
#include <iostream>
#include <memory>
using namespace std;
class MyOtherClass
{
public:
MyOtherClass()
{
throw std::runtime_error("not working");
}
};
class MyClass
{
public:
typedef std::unique_ptr<MyOtherClass> MyOtherClassPtr;
MyClass()
{
try
{
other = std::make_unique<MyOtherClass>();
}
catch(...)
{
cout << "initialization failed." << endl;
}
cout << "other is initialized: " << (other ? "yes" : "no");
}
private:
std::unique_ptr<MyOtherClass> other;
};
int main()
{
MyClass c;
return 0;
}
Of course, there are also solutions without using exceptions at all but I assumed that this is a prerequisite in your setting.
I don't see how you'd do that with initializer-list syntax, but I'm also a bit sceptical that you'll be able to do anything useful by catching the exception in your constructor. It depends on the design of the classes, obviously, but in what case are you going to fail to create "mB", and still have a useful "A" object?
You might as well let the exception percolate up, and handle it wherever the constructor for A is being called.

Catching exceptions from a constructor's initializer list

Here's a curious one. I have a class A. It has an item of class B, which I want to initialize in the constructor of A using an initializer list, like so:
class A {
public:
A(const B& b): mB(b) { };
private:
B mB;
};
Is there a way to catch exceptions that might be thrown by mB's copy-constructor while still using the initializer list method? Or would I have to initialize mB within the constructor's braces in order to have a try/catch?
Have a read of http://weseetips.wordpress.com/tag/exception-from-constructor-initializer-list/)
Edit: After more digging, these are called "Function try blocks".
I confess I didn't know this either until I went looking. You learn something every day! I don't know if this is an indictment of how little I get to use C++ these days, my lack of C++ knowledge, or the often Byzantine features that litter the language. Ah well - I still like it :)
To ensure people don't have to jump to another site, the syntax of a function try block for constructors turns out to be:
C::C()
try : init1(), ..., initn()
{
// Constructor
}
catch(...)
{
// Handle exception
}
It's not particularly pretty:
A::A(const B& b) try : mB(b)
{
// constructor stuff
}
catch (/* exception type */)
{
// handle the exception
}
I know it has been awhile since this discussion started. But that try-and-catch construct mentioned by Adam is part of the C++ standard and is supported by Microsoft VC++ and GNU C++.
Here is the program that works. By the way the the catch generates automatically another exception to signal about the constructor failure.
#include <iostream>
#include <exception>
#include <string>
using namespace std;
class my_exception: public exception
{
string message;
public:
my_exception(const char* message1)
{
message = message1;
}
virtual const char* what() const throw()
{
cout << message << endl;
return message.c_str();
}
virtual ~my_exception() throw() {};
};
class E
{
public:
E(const char* message) { throw my_exception(message);}
};
class A
{
E p;
public:
A()
try :p("E failure")
{
cout << "A constructor" << endl;
}
catch (const exception& ex)
{
cout << "Inside A. Constructor failure: " << ex.what() << endl;
}
};
int main()
{
try
{
A z;
}
catch (const exception& ex)
{
cout << "In main. Constructor failure: " << ex.what() << endl;
}
return 0;
}
You could work with lazy initialization, though, that is hold a unique_ptr to Reader in MyClass and create it with new. That way, you do not even need the flag has_reader but you can just see if your unique_ptr is initial or not.
#include <iostream>
#include <memory>
using namespace std;
class MyOtherClass
{
public:
MyOtherClass()
{
throw std::runtime_error("not working");
}
};
class MyClass
{
public:
typedef std::unique_ptr<MyOtherClass> MyOtherClassPtr;
MyClass()
{
try
{
other = std::make_unique<MyOtherClass>();
}
catch(...)
{
cout << "initialization failed." << endl;
}
cout << "other is initialized: " << (other ? "yes" : "no");
}
private:
std::unique_ptr<MyOtherClass> other;
};
int main()
{
MyClass c;
return 0;
}
Of course, there are also solutions without using exceptions at all but I assumed that this is a prerequisite in your setting.
I don't see how you'd do that with initializer-list syntax, but I'm also a bit sceptical that you'll be able to do anything useful by catching the exception in your constructor. It depends on the design of the classes, obviously, but in what case are you going to fail to create "mB", and still have a useful "A" object?
You might as well let the exception percolate up, and handle it wherever the constructor for A is being called.