EDIT : Summary of answers
In the following, B is a subclass of A.
It\'s a matter of terminology; ctors and dtors are not in
In your example, you're explicitly calling the destructor functions. This is legal (obviously, since it compiled and ran) but almost always incorrect.
For dynamically-allocated objects created with new, the destructor will be run when the objected is removed with delete.
For statically-allocated objects, which are created simply by declaring the object within the scope of a function, the destructor is run when the object's scope disappears. That is, when main() exits, the objects' destructors will be run. But you've already run the destructors for those objects by calling them manually! This is why your example's output shows the count decreasing to -3... you've run the destructors for a, b, and c twice.
Here's the same code, annotated to show when destructors will be automatically run:
int main()
{
printf("Create A\n"); A a;
printf("Delete A\n"); a.~A();
printf("Create B\n"); B b;
printf("Delete B\n"); b.~B();
printf("Create new B stored as A*\n"); A *a_ptr = new B();
printf("Delete previous pointer\n");
delete a_ptr; // Implicitly calls destructor for a_ptr. a_ptr is class B,
// so it would call a_ptr->~B() if it existed. Because B is an A, after
// its destructor is called, it calls the superclass's destructor,
// a_ptr->~A().
printf("Create C\n"); C c;
printf("Delete C\n"); c.~C();
}
// Function exits here at the close brace, so anything declared in its scope is
// deallocated from the stack and their destructors run.
// First `c` is destroyed, which calls c.~C(), then because C is a subclass of A
// calls c.~B() (which doesn't exist, so a blank implementation is used), then
// because B is a subclass of A calls c.~A(). This decrements the counter, but
// the count is wrong because you already manually called c.~C(), which you
// ordinarily shouldn't have done.
// Then `b` is destroyed, in a similar manner. Now the count is off by 2,
// because you had already called b.~B().
// Lastly `a` is destroyed, just as above. And again, because you had already
// called a.~A(), the count is now off by 3.