Reputation: 4609
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
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