Search code examples
c++destructorpure-virtualvirtual-destructor

C++: Pure virtual destructor in abstract class with members


I've just started learning C++ and stumbled across this problem.. I've written this abstract class with pure virtual destructor:

#ifndef ANIMAL
#define ANIMAL
#include <string>
using namespace std;

class Animal {
public:
    Animal();
    virtual ~Animal() = 0;
    Animal(string name, int age);
    virtual string says() = 0;
    void setName(string name);
    void setAge(int age);
    string getName() const;
    int getAge() const;

private:
    int _age;
    string _name;
};
inline Animal::~Animal() { }

Created dynamically and destroyed like this...

Animal** animalArray = new  Animal*[10];
animalArray[0] = new Dog(name, age);
animalArray[1] = new Cat(name, age);
animalArray[2] = new Owl(name, age);

delete[] animalArray;

and I am left wondering if an Animal object is created dynamically and then destroyed, will the _age and _name members get destroyed properly since the destructor for Animal class is empty? If so, why?

Thanks :D


Solution

  • In the example you posted, you're actually not destroying everything correctly. In the line

    delete[] animalArray;
    

    you are deleting an array of Animal*s. Note that this does not automatically destroy the things being pointed to! You would have to do:

    for(int i = 0; i < 3; ++i)
        delete animalArray[i];
    delete[] animalArray;
    

    This destroys each element, then destroys the container.

    Now, your actual question is asking whether the private member variables are going to be cleanly destroyed. The answer is yes--after your destructor runs, any statically allocated variables' destructors will also be called by the compiler. It is their obligation to clean up after themselves. When you're doing polymorphism as in your example, the (empty) destructor Animal::~Animal will indeed be called.

    Note that this carries the same warning as the code above: if you instead have

    string* _name;
    

    that you dynamically allocate in the constructor (with new), then the string* will be destroyed, but the pointed to string will not be. So in that case, you would have to manually call delete to properly clean up.