i am unable to understand why 'calling ~Base()' is been printed here? |
Short answer: "That's just how the language works"
Long answer:
Encapsulation is the idea that every class manages and takes care of itself. In order to facilitate this, every object needs to be constructed and destructed. If a destructor or constructor is not called for a class, you risk very bad side-effects (memory leaks or memory corruption, or other equally terrible bugs).
C++ implements this as illustrated below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class Parent
{
public:
Parent() { cout << "Parent ctor\n"; }
~Parent() { cout << "Parent dtor\n"; }
};
class Child : public Parent
{
public:
Child() { cout << "Child ctor\n"; }
~Child() { cout << "Child dtor\n"; }
}
int main()
{
{
Child c;
}
}
|
Parent ctor
Child ctor
Child dtor
Parent dtor | |
This guarantees the coder that the 'Parent' part of the object will be initialized and 'alive' throughout the entire life of the Child object.... since the Child portion is initialized second and destroyed first.
If you take those same classes (with no virtual dtor) and do this, you have problems:
1 2 3 4 5
|
int main()
{
Parent* p = new Child;
delete p;
}
|
Parent ctor
Child ctor
Parent dtor | |
(not I'm not sure this exact behavior is defined by the standard, but this is what will happen on most if not all implementations).
See the problem here? Child is constructed but is never destructed. This destroys encapsulation and allows for nastiness as described above (memory and other resource leaks, deadlocks, etc, etc)
This happens because the compiler only sees us deleting a Parent*. It does not know that the pointer actually points to a Child and therefore it will not call the Child dtor.
Making the destructor virtual puts the destructor in the class's vtable... which means it can figure out the type (and call the appropriate dtor) at runtime.