Reputation: 3355
using namespace std;
class C
{
int a;
public:
C(int aa=0) {a=aa;}
~C() {cout << "Destructor C!" << a << endl;}
};
class D: public C
{
int b;
public:
D(int aa=0, int bb=0): C(aa) {b=bb;}
~D() {cout << "Destructor D!" << b << endl;}
};
void test()
{
D x(5);
D y(6,7);
}
int main()
{
test();
}
Above is the code, and below is the running result:
Destructor D!7
Destructor C!6
Destructor D!0
Destructor C!5
I don't understand why "Destructor C!" will be invoked. And the related destructor's calling sequence. I feel that it seems like the stack push/pop.
Further: Why it calls "D x(5);" earlier but the corresponding result is given later?
Upvotes: 2
Views: 4999
Reputation: 1691
Further: Why it calls "D x(5);" earlier but the corresponding result is given later?
These objets are allocated on the stack (while D * d1 = new D();
would allocate on the heap).
It is not the call to D x(5)
which gives output, but the call to the destructor ~D
occuring when the instance gets out of scope, in this case, when exiting main()
.
Because it's stack memory, the desallocations occur in reverse order to the allocation;
Upvotes: 0
Reputation: 726479
The destructor calling sequence always goes from the derived to base, like popping the stack. This allows derived classes to clean up resources allocated by your base class. In this case, the compiler knows how to construct this sequence, because it knows the exact type of the objects x
and y
statically.
There are situations, however, when this sequence would be broken. Consider the following modification of your code:
void test()
{
C *x = new D(5);
D *y = new D(6,7);
delete x;
delete y;
}
It produces the following output:
Destructor C!5
Destructor D!7
Destructor C!6
Running this produces no call of ~D
for x
; for y
, both destructors are called.
This is because you did not declare the destructor virtual
in the base class. When the destructor is not virtual, the compiler has no idea that it must call the destructor of the derived class in situations when an object is referred to by a pointer to a base class. This is why you should always make a destructor virtual in classes that must be inherited and allocate resources dynamically.
Upvotes: 3
Reputation: 45410
I feel that it seems like the stack push/pop.
class D derived from C, when call D constructor, C constructor will be called first, destructor is called the reverse way.
Further: Why it calls "D x(5);" earlier but the corresponding result is given later?
Automatic objects (commonly referred to as "local variables") are destructed, in reverse order of their definition, when control flow leaves the scope of their definition.
Upvotes: 2
Reputation: 171107
The destructor of C
is called because destroying an object of a derived class includes destroying its base class subobject. As per [class.dtor] para 8:
After executing the body of the destructor ... a destructor for class X calls ... the destructors for X's direct base classes ...
When control flow exits a scope (such as your function test()
ending), local objects are destroyed in LIFO manner: objects created first are destroyed last. As per [stmt.jump] para 2:
On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction.
Upvotes: 0
Reputation: 3988
The constructor and destructor calling sequence for a derived class is as follows:
Base Class Constructor
Derived Class Constructor
Derived Class Destructor
Base Class Destructor
As a derived class is built on top a base class:
Upvotes: 3
Reputation: 13651
When you inherit, you "extend" the object you inherit from. So if you want to build D
, you need C
. And when you need to destroy D
, you will the destroy C
, which you build to be able to extend it.
Upvotes: 1
Reputation: 63190
When you create a D
instance, the constructor of C
will be called because D
inherits from it.
When you destroy D
again, it'll call D
s destructor and then C
destructor.
Upvotes: 1
Reputation: 20760
When an objected is cleaned up, first the destructor of the derived class is called, then the destructor of the base class.
Upvotes: 1