void.pointer
void.pointer

Reputation: 26405

How do you implement the destructor in CRTP?

Are destructors required to be virtual when implementing curiously recurring template pattern (CRTP)? And if not, what is the proper non-virtual implementation?

I'll provide an example to hopefully make things easier:

template<typename T>
class Base
{
public:
    virtual ~Base()
    {
        // Should this be virtual? Non-virtual?
        std::cout << "Base::~Base()\n";
    }
};

class Derived : public Base<Derived>
{
public:
    ~Derived() override
    {
        std::cout << "Derived::~Derived()\n";
    }
};

int main()
{
    Base<Derived>* b = new Derived;
    delete b;
}

Result:

Derived::~Derived()
Base::~Base()

(Live Sample Here)

EDIT: Updated the example to use runtime polymorphism so that the virtual destructor is required for proper cleanup.

Upvotes: 5

Views: 2469

Answers (3)

Fire Lancer
Fire Lancer

Reputation: 30145

In the example you showed, a virtual destructor is not needed. A virtual destructor is just needed when you may need to call it using a pointer to the base class, the same as an overriden function must be virtual in this case. And in the case of a CRTP class like you showed, there is rarely a need to delete a Base<T> instead of T itself.

int main()
{
    Derived *a = new Derived();
    // we have the right type anyway, so dont actually need a virtual anything (even normal virtual methods)
    delete a;

    Derived *a = new Dervied();
    Base<Derived> *b = a;
    // We are now deleting via a parent class, so this needs a virtual destructor.
    // This is pretty uncommon with a simple CRTP however.
    delete b;
}

Upvotes: 3

Hatted Rooster
Hatted Rooster

Reputation: 36503

If you're going to call delete on a pointer of a base class that's pointing to a derived object then you need a virtual destructor, that's all there is to it. CRTP or no CRTP.

Upvotes: 0

Joseph Thomson
Joseph Thomson

Reputation: 10433

A CRTP base class is no different from any other base class in this sense. You will need a virtual destructor only if you are going to delete an object of type Derived via a pointer to Base<Derived>. Otherwise, a virtual destructor is not required.

Base<Derived>* b = new Derived;
delete b; // Base<Derived>::~Base<Derived> must be virtual

Upvotes: 6

Related Questions