tags:

views:

113

answers:

2

I am using gcc. I am aware how the virtual destructors solve the problem when we destroy a derived class object pointed by a base class pointer. I want to know how do they work?

class A
{
      public:
      A(){cout<<"A constructor"<<endl;}
     ~A(){cout<<"A destructor"<<endl;}

};

class B:public A
{
      public:
      B(){cout<<"B constructor"<<endl;}
      ~B(){cout<<"B destructor"<<endl;}
};       

int main()
{
  A * a = new B();
  delete a;    
  getch();
  return 0;   
} 

When I change A's destructor to a virtual function, the problem is solved. What is the inner working for this. Why do I make A's destructor virtual. I want to know what happens to the vtable of A and B?

+5  A: 

Virtual destructor is just a virtual function, so it adheres to the same rules.

When you call delete a, a destructor is implicitly called. If the destructor is not virtual, you get called a->~A(), because it's called as every other non-virtual function.

However if the destructor is virtual, you get ~B() called, as expected: the destructor function is virtual, so what gets called is the destructor of derived class, not base class.

Edit:
Note that the destructor of the base class will be called implicitly after the destructor of the derived class finishes. This is a difference to the usual virtual functions.

Vlad
but shouldn't virtual functions have the same name?
Bruce
@Jack: usually yes; destructor is an exception.
Vlad
@Jack: That would not be possible for destructors - they must have the same name as the class they belong to.
sharptooth
Luckily, the compiler treats all destructors as if they where the same function, "destroy()". So virtual overriding of the destructor works.
Little Bobby Tables
@Jack: this is so because of C++ conventions. In Delphi, for example, destructor can have name different from class name.
Vlad
@Little Bobby Tables: Why doesn't the same problem occur in the case of constructors?
Bruce
@Jack: there are no virtual constructors in C++ :-(
Vlad
@Vlad: I know I might sound stupid but why wouldn't the same problem occur in case of constructors? I mean shouldn't compiler just call the base class constructor?
Bruce
@Jack: there is no construction polymorphism in C++: with constructors, you always get an instance of the class according to the constructor you called. With destruction, it's more complicated: you can destroy an object by a pointer to the base class.
Vlad
@Jack: because you tell the compiler *explicitly* which constructor to call so the compiler *knows* which one to call.
Konrad Rudolph
@Jack: please note that virtual constructor actually makes sense. See http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8 for more details.
Vlad
@Vlad: Virtual destructors are no exception to the rule that virtual functions have the same name. They do have the same name as the base class' destructor. Destructors are unnamed. `~MyObject` is just what you type to refer to the destructor -- it's not the destructor's name.
John Dibling
@Jack: When you call `B* b = new B` and `B` is derived from `A`, the `A` constructor is called within the initialization list for B.
John Dibling
@John: it's a question of convention. I prefer to _call_ `~A` a name for destructor of class `A`, because it can be used to refer to the destructor. After all, this is the essence of name -- you use it to refer to something.
Vlad
@Vlad: Understood, but it's not just a matter of convention. According to the C++ standard, constructors and destructor are unnamed.
John Dibling
@John: Section 12.4 of standard (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf), paragraph 12 says: "In an explicit destructor call, the destructor **name** appears as a ~ followed by a type-name that names the destructor’sclass type." Doesn't this disprove your statement?
Vlad
John Dibling
@Vlad: I've posted a clarifying question, take a look: http://stackoverflow.com/questions/2693199/do-destructors-have-names-according-to-the-standard
John Dibling
@John: thanks a lot, the question turned out to be by no means simple.
Vlad
+3  A: 

The key thing you need to know is that not using a virtual destructor in the above code is undefined behavior and that's not what you want. Virtual destructors are like any other virtual functions - when you call delete the program will decide what destructor to call right in runtime and that solves your problem.

sharptooth
@sharptooth: Why doesn't the same problem occur in the case of constructors?
Bruce
@Jack When you constructed your object, you explicitly called `new B()`, so at that point the object is unambiguously a `B`, and so the `B` constructor was called. But when the object was deleted, what you deleted was an `A*`, so it is treated as if it were an `A` object, and so the `A` destructor is called unless it is virtual.
Tyler McHenry
@Tyler McHenry: Thanks a lot that really cleared a lot of thing for me :)
Bruce