Do I need to implement my own destructors for my derived classes if they don't contain static data?

1.2k views Asked by At

Let's say I have:

class Base {
public:
    virtual ~Base() = 0;
}

class Derived: public Base {
public:
    ~Derived();
}

In my code I need to delete Derived classes through a Base pointer, like this:

delete[] pt_base;

However, I don't actually have anything to destroy in the implemented destructors. But I still need them to delete through the base class?

What's the best way to achieve what I want without a whole lot of wasted code and empty destructors?

2

There are 2 answers

13
πάντα ῥεῖ On BEST ANSWER

No, virtual destructor declaration/definition of the Base class is sufficient, though making it abstract requires you give this destructor in the Derived class.

If you just declare

class Base {
public:
    virtual ~Base() {} // <<< Have a definition
};

you don't need to specify any destructors in inherited classes.

0
Lightness Races in Orbit On

If you want to provide a destructor with a "default" implementation, then the default keyword is provided for precisely this purpose. It results in a user-declared destructor that has the same behaviours as an implicitly-defined one.

class Derived : public Base {
public:
    ~Derived() = default;
}

This is equivalent to providing an empty destructor body like {}, but may better display your intent.

But, no, you don't need to provide these destructors:

[C++11: 12.4/4]: If a class has no user-declared destructor, a destructor is implicitly declared as defaulted (8.4). An implicitly-declared destructor is an inline public member of its class.

[C++11: 12.4/5]: A defaulted destructor for a class X is defined as deleted if:

  • X is a union-like class that has a variant member with a non-trivial destructor,
  • any of the non-static data members has class type M (or array thereof) and M has a deleted destructor or a destructor that is inaccessible from the defaulted destructor,
  • any direct or virtual base class has a deleted destructor or a destructor that is inaccessible from the defaulted destructor,
  • or, for a virtual destructor, lookup of the non-array deallocation function results in an ambiguity or in a function that is deleted or inaccessible from the defaulted destructor.

[..]

None of these rules apply here, and no rule exists to change this behaviour in the case that a base class has a pure or impure virtual destructor, so the implicitly-declared destructor in my example above is not deleted (i.e. valid).

The following wording is another strong clue that the derived destructor can be declared for you:

[C++11: 12.4/9]: A destructor can be declared virtual (10.3) or pure virtual (10.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.


Unfortunately you won't be able to use default for the Base class if you want the destructor to be pure; you'll still have to provide its [empty] definition separately:

class Base {
public:
    virtual ~Base() = 0;
};

Base::~Base() {}