In C++ Inheritance, Derived Class Destructor Not Called When Pointer Object to Base Class Is Pointed to Derived Class

In C++ Inheritance, Derived class destructor not called when pointer object to base class is pointed to derived class

Your code has undefined behavior. The base class's destructor must be virtual for the following to have defined behavior.

Base* b = new Derived;    
delete b;

From the C++ standard:

5.3.5 Delete

3 In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.

So in your case, the static type is Base, and the dynamic type is Derived. So the Base's destructor should be:

virtual ~Base() {cout << "Base Destructor\n"; }

C++ destructor not working as intended

You should make the destructor of Aa virtual:

class Aa {
public:
virtual ~Aa();
};

This is a basic concept of c++. You can read on it here (and in many other places).

Virtual Destructor Not called in Base as well as Derived Class

You must decide who owns the SalaryTable that each Lecturer receives a pointer to at construction.
There are two similar options.

(1) the table is explicitly owned by another class/code (not shown in your question), then the Lecturer should keep an observing pointer (or reference) to the table (a const SalaryTable*const or SalaryTable& or similar) which is never used to delete and the code layout must guarantee that a SalaryTable is not destroyed before any Lecturer observing it.

(2) you can ensure this latter using std::shared_ptr, but this comes at some price and also means that there is no owner to the SalaryTable, but that all those parts of code which keep a shared_ptr to it jointly keep ownership.

To me (1) appears the more logical: a SalaryTable is a fundamental object that exists indepedent of any Lecturer and should be created before any Lecturer and destroyed after any Lecturer. I also suggest to avoid shared_ptr if you don't have some experience with it.

Destructor when derived class contains a pointer to base class object

However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way

Since pointerToAnotherDerivedClassObject points at another object in memory, then yes, your DerivedClass destructor needs to explicitly delete that object (or wrap the raw pointer inside a smart pointer - std::auto_ptr, std::unique_ptr, or std::shared_ptr - and let it delete the object for you) ONLY IF DerivedClass is meant to own that other object. Otherwise, do not delete it if you do not own it.

Base class has no destructor, but derived class does. Do I need to look for any pitfalls that DON'T relate to the heap?

Your base class has an implicit destructor. All will be fine.

A virtual base class destructor is used to allow a derived constructor to run when destructing via a pointer or reference to the base class. So in your case, this would be unsafe:

void destruct(Base &b) { b.~Base(); }
Derived d; destruct(d);

But this will be perfectly safe:

void destruct(Derived &d) { d.~Derived(); }
Derived d; destruct(d);

Destructor when derived class contains a pointer to base class object

However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way

Since pointerToAnotherDerivedClassObject points at another object in memory, then yes, your DerivedClass destructor needs to explicitly delete that object (or wrap the raw pointer inside a smart pointer - std::auto_ptr, std::unique_ptr, or std::shared_ptr - and let it delete the object for you) ONLY IF DerivedClass is meant to own that other object. Otherwise, do not delete it if you do not own it.

Why base class destructor (virtual) is called when a derived class object is deleted?

The Standard says

After executing the body of the destructor and destroying any automatic objects allocated within the body,
a destructor for class X calls the destructors for X’s direct non-variant members,the destructors for X’s direct
base classes
and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for
X’s virtual base classes
. All destructors are called as if they were referenced with a qualified name, that is,
ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed
in the reverse order of the completion of their constructor
(see 12.6.2). A return statement (6.6.3) in a
destructor might not directly return to the caller; before transferring control to the caller, the destructors
for the members and bases are called. Destructors for elements of an array are called in reverse order of
their construction (see 12.6).

Also as per RAII resources need to be tied to the lifespan of suitable objects and the destructors of respective classes must be called upon to release the resources.

For example the following code leaks memory.

 struct Base
{
int *p;
Base():p(new int){}
~Base(){ delete p; } //has to be virtual
};

struct Derived :Base
{
int *d;
Derived():Base(),d(new int){}
~Derived(){delete d;}
};

int main()
{
Base *base=new Derived();
//do something

delete base; //Oops!! ~Base() gets called(=>Memory Leak).
}

I wonder why there is an error calling the destructor in the inheritance

Your code invokes undefined behavior.
Excerpt from the "Effective C++" book by Scott Meyers explains why:

When derived class object is deleted through a pointer to a base class
with a non-virtual destructor, results are undefined.

Your base class A should have a virtual destructor:

virtual ~A() { std::cout << "A Destroyer" << '\n'; }

If classes are meant to be used in polymorphic ways then the base class should have the virtual destructor.



Related Topics



Leave a reply



Submit