I have a base class A
with a virtual destructor. A
has descendants B
and C
which use the default destructor. Is it safe to delete an object of C
through a pointer to A
?
More specifically, consider this sample code:
class A {
public:
A(){};
virtual ~A() {/* code here */};
};
class B: public A {
B() {/* code....*/};
/* NO DESTRUCTOR SPECIFIED */
};
class C: public B {/*same as above, no destructor */};
class D: public B {/* same as above, no destructor*/}
The code to be run looks something like this:
A* getAPointer(void); /* a function returning a C or a D*/
A* aptr=getAPointer();
/* aptr is declared as A*, but points to either an object of class C
or class D*/
delete aptr;
Is the delete aptr
safe? Does it do the right thing: if aptr
points to an object of class C
, the aptr
first calls C
's destructor, then B
's destructor, and finally A
's destructor ?
The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration) The destructor is not virtual (that is, the base class destructor is not virtual) All direct base classes have trivial destructors.
The default destructor calls the destructors of the base class and members of the derived class. The destructors of base classes and members are called in the reverse order of the completion of their constructor: The destructor for a class object is called before destructors for members and bases are called.
If your base class destructor is virtual then objects will be destructed in a order(firstly derived object then base ). If your base class destructor is NOT virtual then only base class object will get deleted(because pointer is of base class "Base *myObj"). So there will be memory leak for derived object.
Deleting a derived class object using a pointer of base class type that has a non-virtual destructor results in undefined behavior. To correct this situation, the base class should be defined with a virtual destructor. For example, following program results in undefined behavior.
Is it safe to delete an object of C through a pointer to A?
Yes, it is totally safe as all the destructors in classes B
, C
and D
will be implicitly virtual.
From:
15.4 Destructors [class.dtor]
10 A destructor can be declared virtual (13.3) or pure virtual (13.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
As A
has a virtual destructor, then B
, and C
, D
respectively, have virtual destructors and:
delete aptr;
works correctly.
Yes, it's safe. Adding virtual
to the destructors of your derived classes is redundant.
Consider how the mechanism works. When delete
is used, the runtime needs to know with which destructor the destruction chain should begin. If the static type of the delete
operand has a virtual
destructor, then that's already sufficient for the runtime to know that it must take the extra trouble and inspect the dynamic type.
In your case, it finds that the dynamic type is C
, so C::~C
is called. C::~C
automatically leads to B::~B
and that one automatically leads to A::~A
.
A requirement for C
's (or B
's) destructor to be virtual
would be pointless. After all, the runtime has to find out the dynamic C
type anyway if A::~A
is virtual
. At that point, it doesn't care whether C::~C
is virtual
or not. What difference would it make?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With