Search code examples
c++inheritancemultiple-inheritance

Why does my virtual destructor executes these many times?


I have been practicing with inheritance, and I found that calling the destructor from a base class pointer to an inherited class, results into a strange output, where I find that my destructor executes more times than it should. Resuming my code (EDIT: Asked for more code):

#include <iostream>

using namespace std;

class B{

public:

    virtual void f(){cout << "f() - B" << endl;}
    virtual void g(){cout << "g() - B" << endl;}
    virtual void h() = 0;
    virtual ~B(){cout << "~B() destructor" << endl;}

protected:

    int b;
};

class D1: virtual public B{

public:

    void f(){cout << "f() - D1" << endl;}
    virtual void g(){cout << "g() - D1" << endl;}
    virtual ~D1(){cout << "~D1() destructor" << endl;}

protected:

    int d1;
};

class D2: virtual public B{

public:

    void f(int i){cout << "f(" << i << ") - D2" << endl;}
    virtual void h(){cout << "h() - D2" << endl;}
    virtual ~D2(){cout << "~D2() destructor" << endl;}

protected:

    int d2;
};

class D3: public D1{

public:
    void g(){cout << "g() - D3" << endl;}
    void h(){cout << "h() - D3" << endl;}

private:

    int d3;
};

class D4: public D1, public D2{

public:

    using D1::f; using D2::f;

    virtual ~D4(){cout << "~D4() destructor" << endl;}

private:

    int d4;
};

void f(B& b){

   cout << "f() out " << endl;
   b.f();
   b.g();
   b.h();
};

int main()
{
    B *pB;
    D2 d2;
    D3 d3;
    D4 d4;
    f(d2);
    f(d3);
    f(d4);
    d4.D1::f();
    d4.f(5);
    d4.f(3.7);
    d4.g();
    d4.h();
    pB = new D4;
    pB -> f();
    dynamic_cast<D4*>(pB)->f(3);
    pB -> g();
    pB -> h();
    delete pB;
}

The final output is:

//Other tests
.
.
.
f(3) - D2
~D4() destructor
~D2() destructor
~D1() destructor
~B()  destructor
~D4() destructor
~D2() destructor
~D1() destructor
~B()  destructor
~D1() destructor
~B()  destructor
~D2() destructor
~B()  destructor

Creation of pB pointer; points to new D4 object; explicit call to D4 f() method and delete call. I was expecting just four destructorcalls; one for each inherited class (D4,D2,D1) and last one for base class (B).

Should these results be normal? Is something wrong with my code?


Solution

  • The code that you provided splits out the following output:

    f(3) - D2
    ~D4() destructor
    ~D2() destructor
    ~D1() destructor
    ~B() destructor
    

    Live Demo

    You're right to expect 4 destructor calls. ~D4()->~D2()->~D1()->~B()

    But judging from your output, you are actually deleting two D4 objects, one D1 object, and another D2 object.

    Update:

    The destructor is called when

    1. You call delete on an object.
    2. It goes out of scope.

    Now to illustrate my point I am going to introduce a custom scope:

    int main()
    {
        B *pB;
        { // custom scope
            D2 d2;
            D3 d3;
            D4 d4;
            f(d2);
            f(d3);
            f(d4);
            d4.D1::f();
            d4.f(5);
            d4.f(3.7);
            d4.g();
            d4.h();
            pB = new D4;
            pB->f();
            dynamic_cast<D4*>(pB)->f(3);
            pB->g();
            pB->h();
        }
        delete pB;
    }
    

    Calling this will print the following output:

    //function calls
    ~D4() destructor <-- inside custom scope
    ~D2() destructor <-- inside custom scope
    ~D1() destructor <-- inside custom scope
    ~B() destructor  <-- inside custom scope
    ~D1() destructor <-- inside custom scope
    ~B() destructor  <-- inside custom scope
    ~D2() destructor <-- inside custom scope
    ~B() destructor  <-- inside custom scope
    ~D4() destructor <-- outside custom scope
    ~D2() destructor <-- outside custom scope
    ~D1() destructor <-- outside custom scope
    ~B() destructor  <-- outside custom scope