This example below illustrates how to prevent derived class from being copied. It's based on a base class where both the copy constructor and copy assignment operator are declared private
.
class Uncopyable
{
protected:
// allow construction and destruction of derived objects...
Uncopyable() {}
~Uncopyable() {}
private:
// but prevent copying...
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
We can use this class, combined with private inheritance, to make classes uncopyable:
class derived: private Uncopyable
{...};
Notice that the destructor in class Uncopyable
is not declared as virtual.
Previously, I learned that
virtual
.virtual
.In this example, the destructor for Uncopyable
is not virtual
, but it is being inherited from. This seems to go against the wisdom I've learned previously.
When and why should destructor in base class NOT be defined as virtual
?
A base class destructor only needs to be virtual
if you might try deallocating an object of a derived type through a pointer of the base type. Consequently, if you only inherit from the base class privately instead of publicly, as would be the case in Uncopyable
, then you don't need to worry about putting in a virtual
destructor, because when using private inheritance you can't get a pointer to the derived object and store it in a pointer to the base type.
Another example might be if you were to use a mixin class like this one that makes a class track the number of object allocations, where the mixin is inherited from to acquire behavior but not to be treated polymorphically:
template <typename T> class Counter {
public:
Counter() { ++numInstances; }
Counter(const Counter&) { ++numInstances );
~Counter() { --numInstances; }
static unsigned getNumInstances() { return numInstances; }
private:
static unsigned numInstances;
}
template <typename T> unsigned Counter<T>::numInstances = 0;
More generally, when using static polymorphism, you don't need virtual destructors because you never treat the classes polymorphically using pointers to the base type. You only use a pointer to the derived type.
There are probably a few other cases I didn't cover here, but these two (private inheritance, mixin classes, and static polymorphism) cover much of the space where virtual destructors aren't required.