Reputation: 3373
When we go out of catch block scope, does the exception destructor get called? (In case we don't rethrow it)
Suppose I have class A, and that its destructor is not virtual. B inherits A. Suppose some function threw object of B class as an exception, and it was caught by a catch block
catch(A& a){
...
}
If the exception destructor should be called when go out of catch scope, in this case only the base class A's destructor will be called?
Cornstalks: live trial result in calling both class destructor.
It contradicts my logic. Explain someone?
Upvotes: 14
Views: 939
Reputation: 283624
Whenever the Standard says that an object is destroyed, it means that the correct most-derived destructor is invoked.
Always.
When you polymorphically delete an object without a virtual destructor, or you terminate (via delete
operator or explicit destructor call) an object of incomplete type and the proper destructor is non-trivial, the Standard does not say that object is destroyed. It does not say that the base class destructor is invoked. It says you have undefined behavior.
Upvotes: 3
Reputation: 385104
when we go out of catch block scope, does the exception destructor is called? (In case we don't rethrow it)
Yes:
[C++11: 15.1/4]:
[..] The exception object is destroyed after either the last remaining active handler for the exception exits by any means other than rethrowing, or the last object of typestd::exception_ptr
(18.8.5) that refers to the exception object is destroyed, whichever is later. [..]
if the exception destructor should be called when go out of catch scope, in this case only the base class A's d'tor will be called?
No:
#include <iostream>
struct A
{
A() { std::cout << "A()"; }
A(const A&) { std::cout << "A(const A&)"; }
A(A&&) { std::cout << "A(A&&)"; }
~A() { std::cout << "~A()"; }
};
struct B : A
{
B() { std::cout << "B()"; }
B(const B&) { std::cout << "B(const B&)"; }
B(B&&) { std::cout << "B(B&&)"; }
~B() { std::cout << "~B()"; }
};
int main()
{
try {
throw B();
}
catch (A&) {
}
}
// Output: A()B()~B()~A()
Upvotes: 5
Reputation: 119099
OK, someone already answered your first question. I'll focus on this one:
if the exception destructor should be called when go out of catch scope, in this case only the base class A's d'tor will be called?
The implementation will always destroy the exception object properly regardless of how it is caught. The implementation constructs the exception object, so it knows how to destroy it. This is not the same as when you call delete
through a pointer, because in that case there is incomplete information about the complete type of the object at that point (it may have been new
ed somewhere else) unless a virtual destructor exists.
Were this not the case, catch (...)
would never work at all.
Upvotes: 5
Reputation: 38218
While I'm not quoting from the standard, it seems that throwing a B
and catching a A&
will result in both A
's and B
's destructors getting called. Live demo:
#include <iostream>
struct A
{
~A() { std::cout << "A::~A" << std::endl; }
};
struct B : public A
{
~B() { std::cout << "B::~B" << std::endl; }
};
void throwit()
{
throw B{};
}
int main()
{
std::cout << "beginning main scope" << std::endl;
{
std::cout << "beginning inner scope" << std::endl;
try
{
std::cout << "calling throwit()" << std::endl;
throwit();
}
catch (A& a)
{
std::cout << "caught exception" << std::endl;
}
std::cout << "ending inner scope" << std::endl;
}
std::cout << "ending main scope" << std::endl;
}
Output:
beginning main scope
beginning inner scope
calling throwit()
caught exception
B::~B
A::~A
ending inner scope
ending main scope
As you can see, both destructors get called. The extra scope printing shows very clearly exactly when the destructors get called (at the end of the catch
block).
Upvotes: 3