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 destructor
calls; 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?
The code that you provided splits out the following output:
f(3) - D2
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
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
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