"Rule of 0" says that we should not declare destructors, copy/move-constructors, and copy/move-assignments for classes that do not manage resources ownership.
But, when we create a base class, we need to declare a virtual destructor for the sake of proper destruction behavior of descendants.
Then, the question is: When a base class is not devised to manage resources, what should we do?
That stating of the rule of zero lacks nuance1.
You should prefer to define none of the five, but if you do define any of them, you should define all of them.
For a polymorphic base class Base
, it's a fairly easy. ~Base
has to be defined, because you need it to be virtual. As it turns out, you want to think about copying and moving, because they generally aren't appropriate. What should a Derived1
instance do to copy (or move from) a Derived2
instance?
So you end up with:
// No copy or moves allowed
class Base {
public:
virtual ~Base() = default;
Base(const Base&) = delete;
Base(Base&&) = delete;
Base& operator=(const Base&) = delete;
Base& operator=(Base&&) = delete;
};
// Subclasses can allow copy or move
class Base {
public:
virtual ~Base() = default;
protected:
Base(const Base&) = default;
Base(Base&&) = default;
Base& operator=(const Base&) = default;
Base& operator=(Base&&) = default;
};
Base
is managing, and then you do fit inside your stating of the rule of zero.