Kartik Anand
Kartik Anand

Reputation: 4609

Reset unique_ptr for protected virtual destructor base class

I'm in a situation where in I've to create an object of either type A or B depending on a condition. Both A and B inherit from the same base class, in this case - Base. The base class has a virtual protected destructor.

The variable is declared as std::unique_ptr<Base> member and then depending on the condition, I use either std::make_unique<A> or std::make_unique<B>.

I'm calling member.reset() but getting a compiler error since the destructor is declared protected. But what I don't understand is why is the compiler not able to call the correct destructor since the destructor is also declared virtual.

But is there some other way to fix this? And why exactly does the virtual destructor not help here?

Full code -

#include <iostream>
#include <memory>

using namespace std;

class Base
{
public:
    Base() = default;

protected:
    virtual ~Base() = default;

private:
    int a;
};

class A : public Base
{
};

class B : public Base
{
};

unique_ptr<Base> get_object(bool cond) {
    if (cond) {
        return make_unique<A>();
    } else {
        return make_unique<B>(); 
    }
}

int main()
{
    cout << "Hello World";
    bool cond;
    cin >> cond;

    unique_ptr<Base> a_or_b = get_object(cond);
    a_or_b.reset();

    return 0;
}

Upvotes: 0

Views: 346

Answers (1)

user17732522
user17732522

Reputation: 76829

The base class has a virtual protected destructor.

I don't see any point in that. Making the destructor protected disallows destroying objects through base class pointers. This makes sense as a protection mechanism if doing so would cause undefined behavior (i.e. if the destructor is non-virtual and the most-derived type different from the base class type).

However, making the destructor virtual intents it to be called through the base class pointer in order to destruct also possibly derived class objects, contradicting the effect of protected.

std::unique_ptr is unable to destroy the object through the base class pointer because of the reason given above. virtual does not change that calling the destructor through the base class pointer is disallowed.

See also the C++ core guidelines rule C.35.

Upvotes: 1

Related Questions