The virtual function is required to ensure the object being shared is appropriately deleted. Unlike a unique_ptr
, shared_ptr
does not require full knowledge of the type when its template is instantiated. E.g. you can do this:
class Foo;
std::shared_ptr<Foo> foo = make_foo();
Note that in the code above we don't have the complete Foo type, just the forward declaration. If we let foo
go out of scope, the object it is pointing to will be correctly deleted because when Foo
was created in make_foo
, a deleter was also created which knows the complete type of Foo
, and hence can call the appropriate destructors. (E.g. Perhaps make_foo
creates a Bar
that inherits from Foo
and returns that. shared_ptr
's will handle this fine.)
The function on the deleter object that shared_ptr
creates to manage the deletion of Foo
will be virtual, allowing shared_ptr
to call the correct destructor.
Roughly this could be something like this:
struct deleter_interface {
virtual void ~deleter_interface = default;
virtual void dispose() = 0;
};
template <typename T>
struct deleter : deleter_interface {
T* ptr_;
deleter(T* ptr) : ptr_(ptr) {}
virtual void dispose() { delete ptr_; }
};
template <typename T>
shared_ptr {
T* ptr_;
deleter_interface* deleter_;
...
};
template <typename T>
shared_ptr<T>::shared_ptr<T>(T* ptr)
: ptr_(ptr), deleter_(new deleter<T>(ptr)) {}
template <typename T>
shared_ptr<T>::~shared_ptr<T>() { deleter_->dispose(); delete deleter_; }
While this seems more complicated that is strictly necessary, it is to allow shared_ptr
to be used without the complete type. For example what if you wanted to do this:
In a.h:
struct Foo;
std::shared_ptr<Foo> a = make_object();
// ... let a go out of scope
And in a.cc:
struct Foo { ... };
struct Bar : Foo { ... };
std::shared_ptr<Foo> make_object() { return std::shared_ptr<Foo>(new Bar); }
If we didn't have the virtual function used in the deleter code, then Bar
would not be destructed correctly. With the virtual function it doesn't matter that the header (a.h) never sees the definition of Foo
or Bar
.