A typical factory design pattern require the base class to declare virtual destructor, but this can be actually avoided using shared_ptr
.
#include <iostream>
#include <memory>
#include <cstdio>
using namespace std;
class Dog {
public:
~Dog() { cout << "dog destroyed\n"; }
};
class Yellowdog : public Dog {
public:
~Yellowdog() { cout << "Yellow dog destroyed.\n"; }
};
class DogFactory {
public:
static shared_ptr<Dog> createYellowdog() {
return shared_ptr<Yellowdog>(new Yellowdog());
}
};
int main(int argc, char *argv[]) {
auto ptr = DogFactory::createYellowdog();
cout << ptr.use_count() << endl;
return 0;
}
In this case the output is yellowdog destroyed
followed by dog destroyed
. But why? Why using shared_ptr
can omit the virtual keyword before ~Dog
?
This is happening because shared_ptr
stores type-erased deleter in the control block, which is created when the first shared_ptr
is created. In your case shared_ptr
is created for yellow dog, and deleter is to call yellow-dog destructor.
When you copy (or copy-construct) one shared_ptr
to another, they share the same control block, and new shared ptr is going to call deleter from the original one - the one which will call yellowdog destructor.
However, it doesn't really make the class polymorphic and suitable for factory implementation - any other non-virtual function in the class will be called based on static type of shared_ptr
, and you do not want this in polymorphic classes.