I\'m a little confused. Basically, I\'ve got 2 different resource managers (AudioLibrary and VideoLibrary) that both inherit from a shared BaseLibrary class. This base class
This is due to the fact that you haven't declared your Media
destructor virtual
. As you can see, if you do, for example:
struct Media {
virtual ~Media() = default;
};
struct AudioLibrary : Media {};
struct VideoLibrary : Media {};
int main() {
std::map<int, std::unique_ptr<Media>> map;
map[0] = std::unique_ptr<Media>(new AudioLibrary());
map[1] = std::unique_ptr<Media>(new VideoLibrary());
}
demo
both destructors will be called.
The default deleter for unique_ptr<T>
is the aptly named default_delete<T>
. This is a stateless functor that calls delete
on its T *
argument.
If you want the correct destructor to be called when a unique_ptr
to a base class is destructed, you must either use a virtual destructor, or capture the derived type in a deleter.
You can do this quite easily using a function pointer deleter and captureless lambda:
std::unique_ptr<B, void (*)(B *)> pb
= std::unique_ptr<D, void (*)(B *)>(new D,
[](B *p){ delete static_cast<D *>(p); });
Of course, this means that you need to add the template argument for your deleter to all uses of unique_ptr
. Encapsulating this in another class might be more elegant.
An alternative to this is to use shared_ptr
, as that does capture the derived type, as long as you create the derived shared_ptr
using std::shared_ptr<D>(...)
or, preferably, std::make_shared<D>(...)
.