Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Who calls the Destructor of the class when operator delete is used in multiple inheritance

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;

}

like image 486
dicaprio Avatar asked Apr 07 '10 11:04

dicaprio


2 Answers

  1. 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

  2. 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.

  3. 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

  1. 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
  2. If the Base class has virtual functions, then the compiler takes the information of destructer from vtable.
    1. 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
    2. If the destructer is virtual the vtable will have correcte address of destructer and compiler will insert proper code over there
like image 59
Yogesh Arora Avatar answered Nov 15 '22 00:11

Yogesh Arora


+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.

like image 26
Rich Avatar answered Nov 14 '22 23:11

Rich