Given the following example:
class BaseClass
{
BaseClass()
{
};
virtual ~BaseClass()
{
this->Cleanup();
};
virtual void Cleanup()
{
// Do cleanup here.
};
};
class Level1DerivedClass : public BaseClass
{
Level1DerivedClass()
{
};
virtual ~Level1DerivedClass()
{
};
virtual void Cleanup()
{
// Call my base cleanup.
BaseClass::Cleanup();
// Do additional cleanup here.
};
};
class Level2DerivedClass : public Level1DerivedClass
{
Level2DerivedClass()
{
};
~Level2DerivedClass()
{
};
void Cleanup()
{
// Call my base cleanup.
Level1DerivedClass::Cleanup();
// Do additional cleanup here.
};
};
main()
{
Level2DerivedClass * derived2 = new Level2DerivedClass();
delete derived2;
return 0;
}
When I delete my derived class reference, I would EXPECT the flow would be as follows:
Level2DerivedClass destructor is executed.
Because Level1DerivedClass destructor is virtual, it would be executed.
Because BaseClass destructor is virtual, it would be executed.
Because BaseClass::Cleanup and Level1DerivedClass::Cleanup are both virtual, the call from the BaseClass 'this' pointer in the BaseClass destructor would executed the implementation of the most derived class - Level2DerivedClass::Cleanup.
Level2DerivedClass::Cleanup calls its parent's Cleanup implementation.
Level1DerivedClass::Cleanup calls its parent's Cleanup implementation.
What is happening is that it is calling the destructors for each level of inheritance (1 - 3) above the way I'm expecting. But when this->Cleanup() is called from the BaseClass destructor, it only executes its own implementation. I don't understand why this is happening because normally when you instantiate a derived class pointer, cast it as a base class pointer, and call a virtual method from the base class pointer (in this case, 'this'), it still runs the derived class implementation (the whole point of 'virtual', yes?). In my example, Level2DerivedClass::Cleanup and Level1DerivedClass::Cleanup never gets called.
The reason I'm setting it up this way is I want to be able to call my Cleanup code without having to destroy my object, which is why I'm abstracting it from the actual destructor body.
If you have suggestions on a more proper way to do this, I'm all ears. But I would also like an explanation of why my setup doesn't work - what am I misunderstanding?
Thank you in advance for your time.
The rule of thumb is: Never Call Virtual Functions during Construction or Destruction.
They don't behave as you might expect; as each destructor finishes, the dynamic type of this is effectively modified. From [class.cdtor] in the C++ standard:
When a virtual function is called directly or indirectly from a constructor (including the mem-initializer or
brace-or-equal-initializer for a non-static data member) or from a destructor, and the object to which the
call applies is the object under construction or destruction, the function called is the one defined in the
constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class derived
from the constructor or destructor’s class, or overriding it in one of the other base classes of the most derived
object.
The Proper Way Of Doing Things is: clean after yourself, and yourself only, in the destructor. Don't clean after your kids or your parents.
If you want to clean up things not from the destructor, You Are Doing It Wrong. In C++ we have this little thing called RAII, Resource Acquisition Is Initialization. But there's also its dual, which does not seem to have an officially sounding name, but here's something that could work: RDID, Resource Disposal Is Destruction.
Of course you don't have to adhere to the RAII/RDID philosophy, but that would be Not The C++ Way.
Related
class Base {
public:
Base(int a) : a_(a) {
//do something
someMethod();
//do something else
};
protected:
int a_;
virtual void someMethod() = 0 {};
};
class Derived : Base {
public:
Derived() {
Base::Base(42);
}
protected:
void someMethod() override {
//realisation
}
};
int main() {
Derived *obj = new Derived();
delete obj;
}
This code doesn't work by two mistakes: base class's default constructor is needed and base class's constructor with parameters can't be called because of using abstract methods
My problem is that someMethod() realised in class Derived is not called at all when I create object of class Derived. Also I don't want to use default constructor of class Base, but compiler is swearing.
How can I correct my code to see functionality that I want?
How can I correct my code to see functionality that I want?
Remove the call to a pure virtual function in the constructor of Base.
Call someMethod in the constructor of the derived class that overrides it instead.
Provide an initialiser to the Base subobject in the member initiliser list. If you don't provide an initialiser to the base, it will be default initialised.
Why this cannot work ?
This design will not work because of the way obects are constructed.
When you construct a Derived, the first thing happening is that a Base object is constructed with a Base constructor. There is no Derived object at this moment, so if you'd invoke the virtual function in the Base constructor, it would be the virtual that would be valid for the Base class until you leave the Base constructor's body.
This is allowed by the standard, but with restrictions:
[base.class.init]/16: Member functions (including virtual member functions) can be called for an object under construction. (...) However,
if these operations are performed in a ctor-initializer (or in a
function called directly or indirectly from a ctor-initializer) before
all the mem-initializers for base classes have completed, the program
has undefined behavior.
These restriction do not apply to virtual functions that are called from the constructor body, since the body is executed after all initializers.
But in your case the virtual function is pure virtual for the Base. So it's UB according to the following clause:
[class.abstract]/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making
a virtual call to a pure virtual function directly or
indirectly for the object being created (or destroyed) from such a
constructor (or destructor) is undefined.
What is the alternative
There is unfortunately no other real alternative than using a two step initialization in which you first construct the object and then call an initialization function before using the object.
The only issue with this approach is the risk of forgetting the call to the initialization function. You can protect you against this:
using a flag to indicate if the intialization has taken place and check this flag in all member functions (yes, it's a little overhead).
if you have an abstract class, you may perhaps use a factory pattern (factory method or abstract factory). You could then let the factory do the call.
you may use the builder pattern, and make sure that the constructor is only visible to the builder who won't forget the initialization either.
Other problems with your code
You must be careful about how you "call" the base constructor from the derived constructor:
class Derived : Base {
public:
Derived() : Base(42) // this is the correct place !
{
//Base::Base(42); //<==== OUCH !!! NO !! This creates a temporary base object !!
}
...
};
You'd also need to be careful about the pure virtuals (I don't know if it's a typo or if your compiler could compile your code):
virtual void someMethod() = 0; // if it's abstract, no pending {} !
I know that calling a virtual method from a base class constructor can be dangerous since the child class might not be in a valid state. (at least in C#)
My question is what if the virtual method is the one who initializes the state of the object ? Is it good practice or should it be a two step process, first to create the object and then to load the state ?
First option: (using the constructor to initialize the state)
public class BaseObject {
public BaseObject(XElement definition) {
this.LoadState(definition);
}
protected abstract LoadState(XElement definition);
}
Second option: (using a two step process)
public class BaseObject {
public void LoadState(XElement definition) {
this.LoadStateCore(definition);
}
protected abstract LoadStateCore(XElement definition);
}
In the first method the consumer of the code can create and initialize the object with one statement:
// The base class will call the virtual method to load the state.
ChildObject o = new ChildObject(definition)
In the second method the consumer will have to create the object and then load the state:
ChildObject o = new ChildObject();
o.LoadState(definition);
(This answer applies to C# and Java. I believe C++ works differently on this matter.)
Calling a virtual method in a constructor is indeed dangerous, but sometimes it can end up with the cleanest code.
I would try to avoid it where possible, but without bending the design hugely. (For instance, the "initialize later" option prohibits immutability.) If you do use a virtual method in the constructor, document it very strongly. So long as everyone involved is aware of what it's doing, it shouldn't cause too many problems. I would try to limit the visibility though, as you've done in your first example.
EDIT: One thing which is important here is that there's a difference between C# and Java in order of initialization. If you have a class such as:
public class Child : Parent
{
private int foo = 10;
protected override void ShowFoo()
{
Console.WriteLine(foo);
}
}
where the Parent constructor calls ShowFoo, in C# it will display 10. The equivalent program in Java would display 0.
In C++, calling a virtual method in a base class constructor will simply call the method as if the derived class doesn't exist yet (because it doesn't). So that means that the call is resolved at compile time to whatever method it should call in the base class (or classes it derived from).
Tested with GCC, it allows you to call a pure virtual function from a constructor, but it gives a warning, and results in a link time error. It appears that this behavior is undefined by the standard:
"Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (class.virtual) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined."
With C++ the virtual methods are routed through the vtable for the class that is being constructed. So in your example it would generate a pure virtual method exception since whilst BaseObject is being constructed there simply is no LoadStateCore method to invoke.
If the function is not abstract, but simply does nothing then you will often get the programmer scratching their head for a while trying to remember why it is that the function doesn't actually get called.
For this reason you simply can't do it this way in C++ ...
For C++ the base constructor is called before the derived constructor, which means that the virtual table (which holds the addresses of the derived class's overridden virtual functions) does not yet exist. For this reason, it is considered a VERY dangerous thing to do (especially if the functions are pure virtual in the base class...this will cause a pure-virtual exception).
There are two ways around this:
Do a two-step process of construction + initialization
Move the virtual functions to an internal class that you can more closely control (can make use of the above approach, see example for details)
An example of (1) is:
class base
{
public:
base()
{
// only initialize base's members
}
virtual ~base()
{
// only release base's members
}
virtual bool initialize(/* whatever goes here */) = 0;
};
class derived : public base
{
public:
derived ()
{
// only initialize derived 's members
}
virtual ~derived ()
{
// only release derived 's members
}
virtual bool initialize(/* whatever goes here */)
{
// do your further initialization here
// return success/failure
}
};
An example of (2) is:
class accessible
{
private:
class accessible_impl
{
protected:
accessible_impl()
{
// only initialize accessible_impl's members
}
public:
static accessible_impl* create_impl(/* params for this factory func */);
virtual ~accessible_impl()
{
// only release accessible_impl's members
}
virtual bool initialize(/* whatever goes here */) = 0;
};
accessible_impl* m_impl;
public:
accessible()
{
m_impl = accessible_impl::create_impl(/* params to determine the exact type needed */);
if (m_impl)
{
m_impl->initialize(/* ... */); // add any initialization checking you need
}
}
virtual ~accessible()
{
if (m_impl)
{
delete m_impl;
}
}
/* Other functionality of accessible, which may or may not use the impl class */
};
Approach (2) uses the Factory pattern to provide the appropriate implementation for the accessible class (which will provide the same interface as your base class). One of the main benefits here is that you get initialization during construction of accessible that is able to make use of virtual members of accessible_impl safely.
For C++, section 12.7, paragraph 3 of the Standard covers this case.
To summarize, this is legal. It will resolve to the correct function to the type of the constructor being run. Therefore, adapting your example to C++ syntax, you'd be calling BaseObject::LoadState(). You can't get to ChildObject::LoadState(), and trying to do so by specifying the class as well as the function results in undefined behavior.
Constructors of abstract classes are covered in section 10.4, paragraph 6. In brief, they may call member functions, but calling a pure virtual function in the constructor is undefined behavior. Don't do that.
If you have a class as shown in your post, which takes an XElement in the constructor, then the only place that XElement could have come from is the derived class. So why not just load the state in the derived class which already has the XElement.
Either your example is missing some fundamental information which changes the situation, or there's simply no need to chain back up to the derived class with the information from the base class, because it has just told you that exact information.
i.e.
public class BaseClass
{
public BaseClass(XElement defintion)
{
// base class loads state here
}
}
public class DerivedClass : BaseClass
{
public DerivedClass (XElement defintion)
: base(definition)
{
// derived class loads state here
}
}
Then your code's really simple, and you don't have any of the virtual method call problems.
For C++, read Scott Meyer's corresponding article :
Never Call Virtual Functions during Construction or Destruction
ps: pay attention to this exception in the article:
The problem would almost certainly
become apparent before runtime,
because the logTransaction function is
pure virtual in Transaction. Unless it
had been defined (unlikely, but
possible) the program wouldn't link: the linker would be unable to find the necessary implementation of Transaction::logTransaction.
Usually you can get around these issues by having a greedier base constructor. In your example, you're passing an XElement to LoadState. If you allow the state to be directly set in your base constructor, then your child class can parse the XElement prior to calling your constructor.
public abstract class BaseObject {
public BaseObject(int state1, string state2, /* blah, blah */) {
this.State1 = state1;
this.State2 = state2;
/* blah, blah */
}
}
public class ChildObject : BaseObject {
public ChildObject(XElement definition) :
base(int.Parse(definition["state1"]), definition["state2"], /* blah, blah */) {
}
}
If the child class needs to do a good bit of work, it can offload to a static method.
In C++ it is perfectly safe to call virtual functions from within the base-class - as long as they are non-pure - with some restrictions. However, you shouldn't do it. Better initialize objects using non-virtual functions, which are explicitly marked as being such initialization functions using comments and an appropriate name (like initialize). If it is even declared as pure-virtual in the class calling it, the behavior is undefined.
The version that's called is the one of the class calling it from within the constructor, and not some overrider in some derived class. This hasn't got much to-do with virtual function tables, but more with the fact that the override of that function might belong to a class that's not yet initialized. So this is forbidden.
In C# and Java, that's not a problem, because there is no such thing as a default-initialization that's done just before entering the constructor's body. In C#, the only things that are done outside the body is calling base-class or sibling constructors i believe. In C++, however, initializations done to members of derived classes by the overrider of that function would be undone when constructing those members while processing the constructor initializer list just before entering the constructors body of the derived class.
Edit: Because of a comment, i think a bit of clarification is needed. Here's an (contrived) example, let's assume it would be allowed to call virtuals, and the call would result in an activation of the final overrider:
struct base {
base() { init(); }
virtual void init() = 0;
};
struct derived : base {
derived() {
// we would expect str to be "called it", but actually the
// default constructor of it initialized it to an empty string
}
virtual void init() {
// note, str not yet constructed, but we can't know this, because
// we could have called from derived's constructors body too
str = "called it";
}
private:
string str;
};
That problem can indeed be solved by changing the C++ Standard and allowing it - adjusting the definition of constructors, object lifetime and whatnot. Rules would have to be made to define what str = ...; means for a not-yet constructed object. And note how the effect of it then depends on who called init. The feature we get does not justify the problems we have to solve then. So C++ simply forbids dynamic dispatch while the object is being constructed.
From the C++ FAQ:
[11.4] Can I overload the destructor for my class?
No.
I realize this means you cannot change the return type, arguments' types nor the number of arguments. I may be splitting hairs on the syntax of the words, but is it possible to override the Parent's destructor?
class Child : public Parent {
public:
virtual Parent::~Parent() {
// New definition
}
};
And for that matter do it recursively?
class Grandchild : public Child {
public:
Child::Parent::~Parent() {
// An even newer definition
}
};
I've read this and a related post and it makes me think because destructors are not inherited, they cannot be overridden, but I've never seen it explicitly stated.
EDIT: I changed this to reflect the fact that I want to override the Parent's destructor, note Child and Grandchild overriding ~Parent().
The main reason I am doing this is to maintain Parent's interface while changing the way it is destroyed (the entire reason for the child class). I will have something else managing all Parent's created and will explicitly call their destructors at a later time of my choosing.
I may be splitting hairs on the syntax of the words
No, you are definitely not – these are two very different things.
but is it possible to override the destructor?
Yes, and in fact you must do this in many cases. In order for this to work for a polymorphic object, you need to declare the base class destructor as virtual, though:
Parent const& p = Child();
Will properly call p.~Child() at the end of scope because Parent::~Parent is virtual.
Yes, it is possible to override the destructor of a class. In fact, when you define a class hierarchy in which polymorphism is used, you must declare a virtual destructor in the base class.
Overrides of destructors work exactly the same way overrides of normal member functions work in that when you destroy an object by deleteing the object via a pointer to the base class, the destructor of the derived class is properly called. This is why you must have a virtual destructor in the base class for polymorphic hierarchies.
However, there is a difference between virtual destructors and virtual member methods which has nothing to do with the virtual nature of the destructor. That is, when executing code like this:
class A
{
public:
virtual void Foo() {}
virtual ~A() {};
};
class B : public A
{
public:
void Foo() {};
~B() {}
};
int main()
{
A* a = new B;
a->Foo(); // B::Foo() is called
delete a; // B is destroyed via B::~B()
}
...when you call a->Foo(), the method Foo() in B is called. Since B::Foo() doesn't explicitly call A::Foo(), A::Foo() isn't called.
However, when the object is destroyed via delete a;, first the destructor B::~B() is called, and then after that finishes but before control returns to the program, the base class destructor A::~A() is also called.
Of course this is obvious when you think about it, and again this has nothing to do with the virtual nature of the destructor, but it does behave differently than a normal virtual method call, so I thought I'd point it out.
Obligitory Standard Quotation:
[C++03] 12.4/6 : Destructors
After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class X
calls the destructors for X’s direct members, the destructors for X’s
direct base classes and, if X is the type of the most derived class
(12.6.2), its destructor calls the destructors for X’s virtual base
classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual
overriding destructors in more derived classes. Bases and members are
destroyed in the reverse order of the completion of their
constructor (see 12.6.2). A return statement (6.6.3) in a destructor
might not directly return to the caller; before transferring control
to the caller, the destructors for the members and bases are called.
Destructors for elements of an array are called in reverse order of
their construction (see 12.6).
Yes: you can have virtual destructors, and the only reason is to override them in derived classes.
It looks like this:
class Parent {
public:
virtual ~Parent();
};
class Child : public Parent {
public:
virtual ~Child();
};
class Grandchild : public Child {
public:
~Grandchild(); // virtual is inherited here
};
Note that the destructor isn't overridden by name like ordinary functions, because the name is always that of the class whose instance you're destroying.
Note also that the parent class' destructors are always called too, so you don't need to duplicate their cleanup code: read up on member object and base-class sub-object construction and destruction order for the details.
Terminology
overriding a function means implementing a base-class virtual function in a derived class. You can't change the signature at all (except for using covariant return types). So, an override always has the same signature as an inherited virtual function.
overloading a function means implementing multiple functions with the same name (and in some sense the same scope). So, an overload always has a different signature to the others with the same name, doesn't relate directly to virtual dispatch, and isn't necessarily inherited.
Yes; you can, and should, make a destructor virtual, whenever you have a child class which may be destroyed using a reference to the base class. Static code analysis tools will even complain if you don't offer a virtual destructor.
Consider the following example:
class A
{
public:
A() { a = new int; }
virtual ~A() { delete a; }
private:
int *a;
};
class B final : public A
{
public:
B() { b = new int; }
~B() { delete b; }
private:
int *b;
};
int main()
{
A *a = new B();
delete a;
}
If A's destructor was not virtual, then delete a would only call A's destructor, and you would end up with a memory leak. But because it's virtual, both destructors will be called, in the order ~B() -> ~A().
If I have a base class and a derived class, and I delcare the destructor in the parent virtual, but instantiate an object of type subclass, when destroyed it will invoke the parent destructor right(since virtual)? If I also declare a destructor in the derived class, will it call both destructors (base and derived). Thanks in advance :-).
The second part to my question is regarding the first. Why does the base class destructor need to be declared virtual. Don't constrcutors cycle up the hiearchy. They don't share the same name, so where's the need for it? Shouldn't it work the same for destrucotrs, or by default is only one called? Also does through late binding is it able to detect all the classes and object is made of?
EDIT: My question is not just about virtual destructors, but why does it need to be declared virtual, since they should all be called by default.
Yes, parent destructors will be called automatically.
The destructor should be virtualised so a derived instance can be destroyed properly by code that thinks it has a reference to a base class instance.
In very limited circumstances, it is OK not to virtualise, if you really need to save a few cycles on the vtable lookup.
The need for virtual destructors is because of polymorphism. If you have something like the following:
class A { ... };
class B : public A { ... };
void destroy_class(A* input)
{
delete input;
}
int main()
{
B* class_ptr = new B();
destroy_class(class_ptr); //you want the right destructor called
return 0;
}
While a bit of a contrived example, when you delete the passed-in pointer for the destroy_class() function, you want the correct destructor to get called. If the destructor for class A was not declared virtual, then only the destructor for class A would get called, not the destructor for class B or any other derived type of class A.
Stuff like this is very often a fact-of-life with non-template polymorphic data-structures, etc. where a single deletion function may have to delete pointers of some base-class type that actually points to an object of a derived type.
rubixibuc,
Yeah the subclasses destructor is invoked first, then it's superclass... then it's superclass, and so on until we get to Object's destructor.
More here: http://www.devx.com/tips/Tip/13059 ... it's worth the read... only a screen-full, but it's an INFORMATIVE screen-full.
This question may sound too silly, however , I don't find concrete answer any where else.
With little knowledge on how late binding works and virtual keyword used in inheritance.
As in the code sample, when in case of inheritance where a base class pointer pointing to a derived class object created on heap and delete operator is used to deallocate the memory , the destructor of the of the derived and base will be called in order only when the base destructor is declared virtual function.
Now my question is :
1) When the destructor of base is not virtual, why the problem of not calling derived dtor occur only when in case of using "delete" operator , why not in the case given below:
derived drvd;
base *bPtr;
bPtr = &drvd; //DTOR called in proper order when goes out of scope.
2) When "delete" operator is used, who is reponsible to call the destructor of the class? The operator delete will have an implementation to call the DTOR ? or complier writes some extra stuff ? If the operator has the implementation then how does it looks like , [I need sample code how this would have been implemented].
3) If virtual keyword is used in this example, how does operator delete now know which DTOR to call?
Fundamentaly i want to know who calls the dtor of the class when delete is used.
<h1> Sample Code </h1>
class base
{
public:
base(){
cout<<"Base CTOR called"<<endl;
}
virtual ~base(){
cout<<"Base DTOR called"<<endl;
}
};
class derived:public base
{
public:
derived(){
cout<<"Derived CTOR called"<<endl;
}
~derived(){
cout<<"Derived DTOR called"<<endl;
}
};
I'm not sure if this is a duplicate, I couldn't find in search.
int main()
{
base *bPtr = new derived();
delete bPtr;// only when you explicitly try to delete an object
return 0;
}
This is due to tha fact that in this case the compiler know everything about the object to be destructed which in this case is drvd and is of type derived. When drvd goes out of scope the compiler inserts code to call its destructer
delete is a keyword for compiler. When compiler see delete it inserts the code to call the destructer and the code to call operator delete to deallocate the memory.Please keep in mind that keyword delete and operater delete are different.
When compiler sees keyword delete being used for a pointer it needs to generate code for its proper destruction. For this it needs to know the type information of the pointer. The only thing the compiler know about the pointer is the pointer type, not the type of object to which the pointer is pointing to. The object to which the pointer is pointing to may be a base class or a derived class. In some cases the type of object may be very clearly defined for example
void fun()
{
Base *base= new Derived();
delete base;
}
But in most cases it is not, for example this one
void deallocate(Base *base)
{
delete base;
}
So the compiler does not know which destructer to call of base or of derived. This is the way then it works
If the Base class does not have a virtual function (member function or destructer). It directly insetrts thr code to call the destructer of base class
If the Base class has virtual functions, then the compiler takes the information of destructer from vtable.
If destructer is not virtual. The vtable will have the address of base destructer and thats what will be called. This is not right since the proper destructer is not being called here. This is why it is always recommended to declare destructer of base class as virtual
If the destructer is virtual the vtable will have correcte address of destructer and compiler will insert proper code over there
+1 Good question BTW.
Look at how the virtual mechanism works for a non destructor method and you'll find a destructor behaves no differently.
There are 2 mechanism in play which may confuse the issue a little
.
Firstly a mechanism that isn't virtual is happening on construction and destruction of an object. The object is constructed from base class to derived class, in that order, and when destructed the destructor order is the reversed, so derived to based class. Nothing new here.
Consider calling a non virtual method on a based class pointer to a derived class object, what happens? The base class implementation is called. Now consider calling a virtual method from a base class pointer to a derived class object, what happens? The derived version of the method is called. Nothing you didn't already know.
Lets now consider the destructor scenario. Call delete on a base class pointer to a derived class object which has a non virtual destructor. The base class destructor is called, and if the base class had been derived from another class, then it's destructor would get called next. Because the virtual mechanism isn't in play , the derived destructor won't be called because destruction starts from the destructor you call in the hierarchy and works it way down to the base class.
Now consider the virtual destructor case. delete is called on a based class pointer to a derived class object. What happens when you call any virtual method on a base class pointer? The derived version gets called. So our derived class destructor is called . What happens during destruction, the object destructs from derived destructor to base class, but this time we started the destruction at the derived class level because of the virtual method mechanism.
Why does a stack object with either a non virtual or virtual destructor destruct from derived to base class when it goes out of scope? Because the destructor of the declared class is called in this case and the virtual mechanism has nothing to do with it.
The compiler generates all necessary code to call destructors in the right order, whether it be a stack object or member variable going out of scope, or a heap object being deleted.
You instantiate the derived type, when it goes out of scope it calls the destructor, virtual or not.
The compiler will generate code which makes a call to the destructors. It does not all happen on compile time. Code generation does, but lookin up what the address of the dtor is happens at runtime. Think about the case where you have more then 1 derived type and you do the delete using a base pointer.
A base class destructor needs to be virtual to make a polymorphic delete call the dtor of the derived type.
If you want to find out more try overloading new and delete.